ES6's Promise 进击(一)

作者 johansen 日期 2017-04-05
ES6's Promise 进击(一)

上周我们分析了关于promise简单实现,以及promise的特性。这周我们谈谈关于ES6 Promise的API相关的话题。

Promise 实例方法

then方法

Promise 对象拥有两个实例方法 then() 和 catch() 。以下我们将介绍一下他们二者。具体实现代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
getData(method, url){
var promise = new Promise(function(resolve, reject){
var xmlHttp = new XMLHttpRequest();
xmlHttp.open(method, url);
xmlHttp.send();
xmlHttp.onload = function () {
if (this.status == 200 ) {
resolve(this.response);
} else {
reject(this.statusText);
}
};
xmlHttp.onerror = function () {
reject(this.statusText);
};
})
return promise;
}
getData('get','www.xxx.com').then(successFun, failFun)

从以上例子中可以看到,成功和失败的回调函数我们是通过 then() 添加,在 promise 状态改变时分别调用。 promise 构造函数中通常都是异步的,所以 then 方法往往都先于 resolve 和 reject 方法执行。所以 promise 内部需要有一个存储 fulfill 时调用函数的数组和一个存储 reject 时调用函数的数组。我们还可以看到 then 方法可以接收两个参数,且通常都是函数。第一个参数会添加到 fulfill 时调用的数组中,第二个参数添加到 reject 时调用的数组中。当 promise 状态 fulfill 时,会把 resolve(value) 中的 value 值传给调用的函数中,同理,当 promise 状态 reject 时,会把 reject(reason) 中的 reason 值传给调用的函数。

再看一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var p = new Promise(function(resolve, reject){
//resolve(5);
reject(5);
}).then(undefined,function(value){
console.log(value) //5
});
var p1 = new Promise(function(resolve, reject){
reject(new Error('错误'));
throw new Error('test')
});
var p2 = p1.then(function(value){
console.log(value)
}, function(reason){
console.log(reason) //Error: 错误(…)
}).then(function(value){
console.log('fulfill ' + value) // fulfill undefined
}, function(reason){
console.log('reject ' + reason)
});
console.log(p2 == p1);//false

以上例子说明:

  1. then方法支持链式调用,且返回的对象为新的Promise区别于JQuery的链式调用。
  2. 前一个promise对象的reject 不影响新的promise。

再看一个例子:

1
2
3
4
5
6
7
8
9
10
11
var p = new Promise(function(resolve, reject){
resolve(5)
})
var p1 = p.then(undefined, function(value){
console.log(value)
})
var p2 = p1.then(function(value){
console.log('fulfill ' + value) // fulfill 5
}, function(reason){
console.log('reject ' + reason)
})

该例子中 then 第一个参数是 undefined ,且 value 值5被传到了 p1 成功时的回调函数中。上面那个例子中 then 的第二个参数是 undefined ,同样 reason 值也传到了 p1 失败时的回调函数中。这是因当对应的参数不为函数时,会将前一 promise 的状态和值传递下去。

catch方法

promise 含有一个实例方法catch ,从名字上我们就看得出来,它和异常有千丝万缕的关系。其实 catch(onReject) 方法等价于 then(undefined, onReject) ,也就是说如下两种情况是等效的。

1
2
3
4
5
6
7
8
9
10
new Promise(function(resolve, reject){
reject(new Error('error'))
}).then(undefined, function(reason){
console.log(reason) // Error: error(…)
})
new Promise(function(resolve, reject){
reject(new Error('error'))
}).catch(function(reason){
console.log(reason) // Error: error(…)
})

我们提到参数不为函数时会把值和状态传递下去。所以我们可以在多个 then 之后添加一个 catch 方法,这样前面只要 reject 或抛出异常,都会被最后的 catch 方法处理。
例如:

1
2
3
4
5
6
7
8
9
10
11
new Promise(function(resolve, reject){
resolve(5)
}).then(function(value){
taskA()
}).then(function(value){
taskB()
}).then(function(value){
taskC()
}).catch(function(reason){
console.log(reason)
})