diff --git a/docs/promise.md b/docs/promise.md index 716b306..574dea6 100644 --- a/docs/promise.md +++ b/docs/promise.md @@ -2,9 +2,11 @@ ## 基本用法 -ES6原生提供了Promise对象。所谓Promise对象,就是代表了未来某个将要发生的事件(通常是一个异步操作)。它的好处在于,有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象还提供了一整套完整的接口,使得可以更加容易地控制异步操作。Promise对象的概念的详细解释,请参考[《JavaScript标准参考教程》](http://javascript.ruanyifeng.com/)。 +ES6原生提供了Promise对象。所谓Promise对象,就是代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个事件提供统一的API,可供进一步处理。 -ES6的Promise对象是一个构造函数,用来生成Promise实例。下面是Promise对象的基本用法。 +有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象提供的接口,使得控制异步操作更加容易。Promise对象的概念的详细解释,请参考[《JavaScript标准参考教程》](http://javascript.ruanyifeng.com/)。 + +ES6的Promise对象是一个构造函数,用来生成Promise实例。 ```javascript @@ -24,9 +26,9 @@ promise.then(function(value) { ``` -上面代码表示,Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve方法和reject方法。如果异步操作成功,则用resolve方法将Promise对象的状态变为“成功”(即从pending变为resolved);如果异步操作失败,则用reject方法将状态变为“失败”(即从pending变为rejected)。 +上面代码中,Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve方法和reject方法。如果异步操作成功,则用resolve方法将Promise对象的状态,从“未完成”变为“成功”(即从pending变为resolved);如果异步操作失败,则用reject方法将Promise对象的状态,从“未完成”变为“失败”(即从pending变为rejected)。 -promise实例生成以后,可以用then方法分别指定resolve方法和reject方法的回调函数。 +Promise实例生成以后,可以用then方法分别指定resolve方法和reject方法的回调函数。 下面是一个使用Promise对象的简单例子。 @@ -44,7 +46,7 @@ timeout(100).then(() => { ``` -上面代码的timeout方法返回一个Promise实例对象,表示一段时间以后改变自身状态,从而触发then方法绑定的回调函数。 +上面代码中,timeout方法返回一个Promise实例,表示一段时间以后才会发生的结果。一旦Promise对象的状态变为resolved,就会触发then方法绑定的回调函数。 下面是一个用Promise对象实现的Ajax操作的例子。 @@ -60,11 +62,11 @@ var getJSON = function(url) { client.send(); function handler() { - if (this.status === 200) { - resolve(this.response); - } else { - reject(new Error(this.statusText)); - } + if (this.status === 200) { + resolve(this.response); + } else { + reject(new Error(this.statusText)); + } }; }); @@ -79,33 +81,35 @@ getJSON("/posts.json").then(function(json) { ``` -上面代码中,resolve方法和reject方法调用时,都带有参数。它们的参数会被传递给回调函数。reject方法的参数通常是Error对象的实例,而resolve方法的参数除了正常的值以外,还可能是另一个Promise实例,比如像下面这样。 +上面代码中,getJSON是对XMLHttpRequest对象的封装,用于发出一个针对JSON数据的HTTP请求,并且返回一个Promise对象。需要注意的是,在getJSON内部,resolve方法和reject方法调用时,都带有参数。 + +如果调用resolve方法和reject方法时带有参数,那么它们的参数会被传递给回调函数。reject方法的参数通常是Error对象的实例,表示抛出的错误;resolve方法的参数除了正常的值以外,还可能是另一个Promise实例,表示异步操作的结果有可能是一个值,也有可能是另一个异步操作,比如像下面这样。 ```javascript - var p1 = new Promise(function(resolve, reject){ - // ... some code + // ... }); var p2 = new Promise(function(resolve, reject){ - // ... some code + // ... resolve(p1); }) - ``` -上面代码中,p1和p2都是Promise的实例,但是p2的resolve方法将p1作为参数,这时p1的状态就会传递给p2。如果调用的时候,p1的状态是pending,那么p2的回调函数就会等待p1的状态改变;如果p1的状态已经是fulfilled或者rejected,那么p2的回调函数将会立刻执行。 +上面代码中,p1和p2都是Promise的实例,但是p2的resolve方法将p1作为参数,p1的状态就会传递给p2。 + +注意,这时p1的状态决定了p2的状态。如果p1的状态是pending,那么p2的回调函数就会等待p1的状态改变;如果p1的状态已经是fulfilled或者rejected,那么p2的回调函数将会立刻执行。 ## Promise.prototype.then() -Promise.prototype.then方法返回的是一个新的Promise对象,因此可以采用链式写法。 +Promise.prototype.then方法返回的是一个新的Promise对象,因此可以采用链式写法,即then方法后面再调用另一个then方法。 ```javascript getJSON("/posts.json").then(function(json) { return json.post; }).then(function(post) { - // proceed + // ... }); ``` @@ -119,12 +123,12 @@ getJSON("/posts.json").then(function(json) { getJSON("/post/1.json").then(function(post) { return getJSON(post.commentURL); }).then(function(comments) { - // 对comments进行处理 + // ... }); ``` -这种设计使得嵌套的异步操作,可以被很容易得改写,从回调函数的“横向发展”改为“向下发展”。 +then方法还可以接受第二个参数,表示Promise对象的状态变为rejected时的回调函数。 ## Promise.prototype.catch() @@ -133,7 +137,7 @@ Promise.prototype.catch方法是`Promise.prototype.then(null, rejection)`的别 ```javascript getJSON("/posts.json").then(function(posts) { - // some code + // ... }).catch(function(error) { // 处理前一个回调函数运行时发生的错误 console.log('发生错误!', error); @@ -157,7 +161,7 @@ promise.catch(function(error) { console.log(error) }); 上面代码中,Promise抛出一个错误,就被catch方法指定的回调函数捕获。 -如果Promise状态已经变成“已完成”,再抛出错误是无效的。 +如果Promise状态已经变成resolved,再抛出错误是无效的。 ```javascript @@ -223,6 +227,16 @@ promise.then(function(value) { console.log(value) }); 上面代码中,Promise指定在下一轮“事件循环”再抛出错误,结果由于没有指定catch语句,就冒泡到最外层,成了未捕获的错误。 +Node.js有一个unhandledRejection事件,专门监听未捕获的reject错误。 + +```javascript +process.on('unhandledRejection', function (err, p) { + console.error(err.stack) +}); +``` + +上面代码中,unhandledRejection事件的监听函数有两个参数,第一个是错误对象,第二个是报错的Promise实例,它可以用来了解发生错误的环境信息。。 + 需要注意的是,catch方法返回的还是一个Promise对象,因此后面还可以接着调用then方法。 ```javascript