Promise 的一个重要优点是它将逐渐被用作浏览器的异步 API ,统一现在各种各样的 API ,以及不兼容的模式和手法。让我们看两个即将到来的基于 Promise 的 API 。
fetch API 是基于 Promise 的,用于处理 XMLHttpRequest 的一种方式:
fetch(url)
.then(request => request.text())
.then(str => ···)
在实际请求中, fetch()
返回一个 Promise ; text()
也返回一个 Promise ,用于将响应内容转换成字符串。
ES6 中可编程地动态引入模块也是基于 Promise 的:
System.import('some_module.js')
.then(some_module => {
···
})
和事件相比较, Promise 更适合处理一次性的结果。在结果计算出来之前或之后注册回调函数都是可以的,都可以拿到正确的值。 Promise 的这个优点很自然。但是,不能使用 Promise 处理多次触发的事件。链式处理是 Promise 的又一优点,但是事件却不能这样链式处理。
和回调函数比较, Promise 有更干净的函数(或者方法)签名。回调函数的场景,主函数既有输入参数,又有输出参数:
// name 和 opt 是输入参数, (err, string | Buffer) => void 是输出参数
fs.readFile(name, opts?, (err, string | Buffer) => void)
Promise 的场景,所有的参数都是输入参数:
readFilePromisified(name, opts?) : Promise<string | Buffer>
Promise 带来的额外好处是包含了更好的错误处理方式(包含了异常处理),并且写起来很轻松(因为可以重用一些同步的工具,比如 Array.prototype.map()
)。
Promise 可以很好地处理单一异步结果,不适用于:
- 多次触发的事件:如果要处理这种情况,可以了解一下响应式编程( reactive programming ),这是一种很聪明的链式的处理普通事件的方法。
- 数据流:支持此种情形的标准正在制定中。
ECMAScript 6 Promise 缺少两个有时很有用的特性:
- 不能取消执行。
- 无法获取当前执行的进度信息(比如,要在用户界面展示进度条)。
Q Promise 库对于后者提供了支持,并且有计划将两种能力都添加到 Promises/A+
规范中去。