1
0
mirror of https://github.com/ruanyf/es6tutorial.git synced 2025-05-25 03:02:21 +00:00
es6tutorial/docs/promise.md
2014-04-23 21:56:31 +08:00

166 lines
4.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Promise对象
## 基本用法
ES6原生提供了Promise对象。所谓Promise对象就是代表了未来某个将要发生的事件通常是一个异步操作。它的好处在于有了Promise对象就可以将异步操作以同步操作的流程表达出来避免了层层嵌套的回调函数。此外Promise对象还提供了一整套完整的接口使得可以更加容易地控制异步操作。Promise对象的概念的详细解释请参考[《JavaScript标准参考教程》](http://javascript.ruanyifeng.com/)。
ES6的Promise对象是一个构造函数用来生成Promise实例。下面是Promise对象的基本用法。
```javascript
var promise = new Promise(function(resolve, reject) {
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
promise.then(function(value) {
// success
}, function(value) {
// failure
});
```
上面代码表示Promise构造函数接受一个函数作为参数该函数的两个参数分别是resolve方法和reject方法。如果异步操作成功则用resolve方法将Promise对象的状态变为“成功”即从pending变为resolved如果异步操作失败则用reject方法将状态变为“失败”即从pending变为rejected
promise实例生成以后可以用then方法分别指定resolve方法和reject方法的回调函数。
下面是一个用Promise对象实现的Ajax操作的例子。
```javascript
var getJSON = function(url) {
var promise = new Promise(function(resolve, reject){
var client = new XMLHttpRequest();
client.open("GET", url);
client.onreadystatechange = handler;
client.responseType = "json";
client.setRequestHeader("Accept", "application/json");
client.send();
function handler() {
if (this.readyState === this.DONE) {
if (this.status === 200) { resolve(this.response); }
else { reject(this); }
}
};
});
return promise;
};
getJSON("/posts.json").then(function(json) {
// continue
}, function(error) {
// handle errors
});
```
## 链式操作
then方法返回的是一个新的Promise对象因此可以采用链式写法。
```javascript
getJSON("/posts.json").then(function(json) {
return json.post;
}).then(function(post) {
// proceed
});
```
上面的代码使用then方法依次指定了两个回调函数。第一个回调函数完成以后会将返回结果作为参数传入第二个回调函数。
如果前一个回调函数返回的是Promise对象这时后一个回调函数就会等待该Promise对象有了运行结果才会进一步调用。
```javascript
getJSON("/post/1.json").then(function(post) {
return getJSON(post.commentURL);
}).then(function(comments) {
// 对comments进行处理
});
```
这种设计使得嵌套的异步操作,可以被很容易得改写,从回调函数的“横向发展”改为“向下发展”。
## catch方法捕捉错误
catch方法是then(null, rejection)的别名,用于指定发生错误时的回调函数。
```javascript
getJSON("/posts.json").then(function(posts) {
// some code
}).catch(function(error) {
// 处理前一个回调函数运行时发生的错误
});
```
Promise对象的错误具有“冒泡”性质会一直向后传递直到被捕获为止。
```javascript
getJSON("/post/1.json").then(function(post) {
return getJSON(post.commentURL);
}).then(function(comments) {
// some code
}).catch(function(error) {
// 处理前两个回调函数的错误
});
```
## Promise.all方法
Promise.all方法用于将多个异步操作或Promise对象包装成一个新的Promise对象。当这些异步操作都完成后新的Promise对象的状态才会变为fulfilled只要其中一个异步操作失败新的Promise对象的状态就会变为rejected。
```javascript
// 生成一个promise对象的数组
var promises = [2, 3, 5, 7, 11, 13].map(function(id){
return getJSON("/post/" + id + ".json");
});
Promise.all(promises).then(function(posts) {
// ...
}).catch(function(reason){
// ...
});
```
## Promise.resolve方法
有时需要将现有对象转为Promise对象Promise.resolve方法就起到这个作用。
```javascript
var jsPromise = Promise.resolve($.ajax('/whatever.json'));
```
上面代码将jQuery生成deferred对象转为一个新的ES6的Promise对象。
如果Promise.resolve方法的参数不是具有then方法的对象又称thenable对象则返回一个新的Promise对象且它的状态为resolved。
```javascript
var p = Promise.resolve('Hello');
p.then(function (s){
console.log(s)
});
// Hello
```
上面代码生成一个新的Promise对象它的状态为fulfilled所以回调函数会立即执行Promise.resolve方法的参数就是回调函数的参数。