🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
在 [ES6 Promises](http://liubin.github.io/promises-book/#es6-promises) 标准中定义的API还不是很多。 目前大致有下面三种类型。 **Constructor** Promise类似于 `XMLHttpRequest`,从构造函数 `Promise` 来创建一个新建新`promise`对象作为接口。 要想创建一个promise对象、可以使用`new`来调用`Promise`的构造器来进行实例化。 ~~~ var promise = new Promise(function(resolve, reject) { // 异步处理 // 处理结束后、调用resolve 或 reject }); ~~~ **Instance Method** 对通过new生成的promise对象为了设置其值在 **resolve**(成功) / **reject**(失败)时调用的回调函数 可以使用`promise.then()` 实例方法。 ~~~ promise.then(onFulfilled, onRejected) ~~~ resolve(成功)时:`onFulfilled` 会被调用 reject(失败)时:`onRejected` 会被调用 `onFulfilled`、`onRejected` 两个都为可选参数。 `promise.then` 成功和失败时都可以使用。 另外在只想对异常进行处理时可以采用 `promise.then(undefined, onRejected)` 这种方式,只指定reject时的回调函数即可。 不过这种情况下 `promise.catch(onRejected)` 应该是个更好的选择。 ~~~ promise.catch(onRejected) ~~~ **Static Method** 像 `Promise` 这样的全局对象还拥有一些静态方法。 包括 `Promise.all()` 还有 `Promise.resolve()` 等在内,主要都是一些对Promise进行操作的辅助方法。 ## 1.2.1\. Promise workflow 我们先来看一看下面的示例代码。 promise-workflow.js ~~~ function asyncFunction() { // `new` Promise构造器之后,会返回一个promise对象 return new Promise(function (resolve, reject) { setTimeout(function () { resolve('Async Hello world'); }, 16); }); } // 为promise对象用设置 `.then` 调用返回值时的回调函数。 asyncFunction().then(function (value) { console.log(value); // => 'Async Hello world' }).catch(function (error) { console.log(error); }); ~~~ `asyncFunction` 这个函数会返回promise对象, 对于这个promise对象,我们调用它的 `then` 方法来设置resolve后的回调函数, `catch` 方法来设置发生错误时的回调函数。 该promise对象会在setTimeout之后的16ms时被resolve, 这时 `then` 的回调函数会被调用,并输出 `'Async Hello world'` 。 在这种情况下 `catch` 的回调函数并不会被执行(因为promise返回了resolve), 不过如果运行环境没有提供 `setTimeout` 函数的话,那么上面代码在执行中就会产生异常,在 `catch` 中设置的回调函数就会被执行。 当然,像`promise.then(onFulfilled, onRejected)` 的方法声明一样, 如果不使用`catch` 方法只使用 `then`方法的话,如下所示的代码也能完成相同的工作。 ~~~ asyncFunction().then(function (value) { console.log(value); }, function (error) { console.log(error); }); ~~~ ## 1.2.2\. Promise的状态 我们已经大概了解了Promise的处理流程,接下来让我们来稍微整理一下Promise的状态。 用`new Promise` 实例化的promise对象有以下三个状态。 "has-resolution" - Fulfilled resolve(成功)时。此时会调用 `onFulfilled` "has-rejection" - Rejected reject(失败)时。此时会调用 `onRejected` "unresolved" - Pending 既不是resolve也不是reject的状态。也就是promise对象刚被创建后的初始化状态等 关于上面这三种状态的读法,其中 左侧为在 [ES6 Promises](http://liubin.github.io/promises-book/#es6-promises) 规范中定义的术语, 而右侧则是在 [Promises/A+](http://liubin.github.io/promises-book/#promises-aplus) 中描述状态的术语。 基本上状态在代码中是不会涉及到的,所以名称也无需太在意。 在这本书中,我们会基于 [Promises/A+](http://promises-aplus.github.io/promises-spec/) 中 _Pending_ 、 _Fulfilled_ 、_Rejected_ 的状态名称进行讲述。 ![promise-states](https://box.kancloud.cn/2015-07-20_55ac6eaccf64c.png) Figure 1\. promise states > 在 [ECMAScript Language Specification ECMA-262 6th Edition – DRAFT](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-promise-objects) 中 `[[PromiseStatus]]` 都是在内部定义的状态。 由于没有公开的访问 `[[PromiseStatus]]` 的用户API,所以暂时还没有查询其内部状态的方法。 到此在本文中我们已经介绍了promise所有的三种状态。 promise对象的状态,从_Pending_转换为_Fulfilled_或_Rejected_之后, 这个promise对象的状态就不会再发生任何变化。 也就是说,Promise与Event等不同,在`.then` 后执行的函数可以肯定地说只会被调用一次。 另外,_Fulfilled_和_Rejected_这两个中的任一状态都可以表示为**Settled**(不变的)。 Settled resolve(成功) 或 reject(失败)。 从_Pending_和_Settled_的对称关系来看,Promise状态的种类/迁移是非常简单易懂的。 当promise的对象状态发生变化时,用`.then` 来定义只会被调用一次的函数。 > [JavaScript Promises - Thinking Sync in an Async World // Speaker Deck](https://speakerdeck.com/kerrick/javascript-promises-thinking-sync-in-an-async-world) 这个ppt中有关于Promise状态迁移的非常容易理解的说明。