promise

Promise

MDN: promise

顾名思义,Promise意为一种承诺,表明承诺做完一件事,要么成功要么失败,对应每一种结果,我都承诺会给予相应的回应(即解决方法)。

ES6 已自身实现了Promise,可以直接使用。

特点

  • Promise对象对应着三种状态,即PENDING(进行中,还未有结果),FULFILLED(完成态),REJECTED(失败)。
  • Promise对象的状态可以由PENDINGFULFILLEDPENDINGREJECTED转换,且一旦转换,则不再改变。
  • Promise对象一旦发生了改变,即使再对其添加回调,也会立刻得到该结果。(_测试发现确实是这样,但是还不能确定自己理解是正确的_)
  • Promise对象一定有then方法,用以对对象的状态改变后,做出相应的回应。
  • Promise一旦执行则无法中途取消。

用法

1
2
3
4
5
6
7
8
9
10
11
12
13
let p = new Promise((resolve, reject) => {
if (success) {
resolve(val);
}else{
reject(err);
}
});
p
.then((val) => {
// success
}, (err) => {
// failure
})

参数 executor
executor 是一个带有 resolve 和 reject 两个参数的函数 。executor 函数在 Promise 构造函数执行时同步执行,被传递 resolve 和 reject 函数(executor 函数在 Promise 构造函数返回新建对象前被调用)。resolve 和 reject 函数被调用时,分别将 promise 的状态改为 fulfilled(完成)或 rejected(失败)。executor 内部通常会执行一些异步操作,一旦完成,可以调用 resolve 函数来将 promise 状态改成 fulfilled,或者在发生错误时将它的状态改为 rejected。
如果在 executor 函数中抛出一个错误,那么该 promise 状态为 rejected。executor 函数的返回值被忽略。

Promise 简单功能实现

此处代码高度参考 Github:ElemeFE/node-practice

看了好两边遍,自己倒是也尝试着写了好几遍 = =。。实现起来还是感觉很生疏。。每到最后实现多个 then 的时候就会出现问题。。可能自己是真的蠢。。/ 尴尬

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
const FULFILLED = Symbol();
const REJECTED = Symbol();
const PENDING = Symbol();
function Promisee(callback){
let status = PENDING;
let value = null;
let handler = [];
function reject(err) {
value = err;
status = REJECTED;
handler.forEach(next);
handler = [];
}
function resolve(value) {
try {
let then = typeof value.then == 'function' ? value.then : null;
if (then) {
value.then.apply(null, [resolve, reject]);
return;
}
fulfill(v);
} catch (e) {
reject(e);
}
}
function fulfill(val){
status = FULFILLED;
value = val;
next(handler);
handler.forEach(next);
handler = [];
}
function next({onFulfill, onReject}) {
switch (status) {
case PENDING:
handler.push({onFulfill, onReject});
break;
case FULFILLED:
onFulfill && onFulfill(value);
break;
case REJECTED:
onReject && onReject(value);
break;
}
}
this.then = (onFulfill, onReject) => {
return new Promisee((resolve, reject) => {
next({
onFulfill: (val) => {
resolve(onFulfill(val));
},
onReject: (err) => {
reject(onReject(err));
}
});
});
};
callback(resolve, reject);
}
module.exports = Promisee;
  • 经常忘记的是 resolve 方法下,忽略了新对象的 then 方法上下文绑定。
  • 目前对 then 方法实现这块的 next 调用,所谓的_参数拦截_?有点不太明白。这是第一次遇到这种写法。。
  • 还没有做完备的参数检查等异常处理。

几个 Promise 方法

Promise.prototype.catch(onRejected)

指定发生错误时执行的回调。

它可以在 promise/then 中发生异常时,捕获异常并处理。
Promise 对象的错误具有 “冒泡” 性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个 catch 语句捕获。
一般 then 方法里可以不用谢第二个 reject 的回调,可以只写 resolve 回调,然后直接在最后加上 catch 捕获异常。

promise_catch

Promise.all()

Promise.all() 接受一个 Iterable 参数,Iterable 对象的每个子项都是一个 Promise 实例,若不是,则调用 Promise.resolve() 方法将其转换。

Promise.all() 的状态由其 Iterable 对象的所有子项决定

  • 若所有子项都 FULFILLED,则 Promise.all() 的状态才变为 FULFILLED,其 Iterable 的所有子项的返回值组成一个数组,传递给 Promise.all() 的回调。
  • 若有任意一个子项被 REJECT,则 Promise.all() 直接 REJECT,其中第一个被 REJECT 的子项的返回值传递给 Promise.all() 的回调。

Promise.race()

该方法形式上与 Promise.all() 有点类似,但时表现不一样。
Promise.race() 对于其参数 Iterable 对象,若有任意一个子项 FULFILLED,则 Promise.race() 也 FULFILLED,如有任意一个子项 REJECT,则 Promise.race() 也 REJECT。
即 Promise.race() 总是和其 Iterable 对象的第一个出结果的子项具有相同的状态。

Promise.resolve() 和 Promise.reject()

某峰的 ES6 入门这块写的还是很全的。。。
ECMAScript 6 入门
包括后面的Promise.done()Promise.finally()以及Promise.try()