ES6 Promise

Pending(进行中)、Resolved(已完成,又称Fulfilled)和Rejected(已失败)

如果调用resolve函数和reject函数时带有参数,那么它们的参数会被传递给回调函数。reject函数的参数通常是Error对象的实例,表示抛出的错误;resolve函数的参数除了正常的值以外,还可能是另一个Promise实例,表示异步操作的结果有可能是一个值,也有可能是另一个异步操作

1
2
3
4
5
6
7
8
9
10
11
12
var p1 = new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error('fail')), 3000)
})
var p2 = new Promise(function (resolve, reject) {
setTimeout(() => resolve(p1), 1000)
})
p2
.then(result => console.log(result))
.catch(error => console.log(error))
// Error: fail

Promise.prototype.then()Promise.prototype.catch()

Promise实例具有then方法,也就是说,then方法是定义在原型对象Promise.prototype上的。它的作用是为Promise实例添加状态改变时的回调函数。前面说过,then方法的第一个参数是Resolved状态的回调函数,第二个参数(可选)是Rejected状态的回调函数。

then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。

1
2
3
4
5
6
p.then((val) => console.log("fulfilled:", val))
.catch((err) => console.log("rejected:", err));
// 等同于
p.then((val) => console.log("fulfilled:", val))
.then(null, (err) => console.log("rejected:", err));

Promise.all()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Promise.prototype.all = function(promises) {
let results = []
return new Promise((resolve, rejected) => {
for(let i=0; i<promises.length; i++) {
promises[i].then((res) => {
results.push(res)
if (i === promises.length -1) {
resolve(results)
}
}).catch((err) => {
reject(err)
})
}
})
}

Promise.race()

Promise.resolve()

有时需要将现有对象转为Promise对象,Promise.resolve方法就起到这个作用。

1
2
3
Promise.resolve(42).then(function(value){
console.log(value);
});

Promise.reject()

Promise.reject(reason)方法也会返回一个新的Promise实例,该实例的状态为rejected。它的参数用法与Promise.resolve方法完全一致。

手写Promise的polyfill

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
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
function MyPromise(executor) {
this.state = PENDING;
this.value = null;
this.reason = null;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
var self = this;
function resolve(val) {
if (self.state === PENDING) {
self.state = FULFILLED;
self.value = value;
self.onFulfilledCallbacks.forEach(function(fulfilledCallback) {
fulfilledCallback();
});
}
}
function rejected(reason) {
if (self.state === PENDING) {
self.state = REJECTED;
self.reason = reason;
self.onRejectedCallbacks.forEach(function(rejectedCallback) {
rejectedCallback();
});
}
}
try {
executor(resolve, rejected);
} catch (reason) {
reject(reason);
}
}
MyPromise.prototype.then = function(onResolve, onRejected) {
if (self.state === PENDING) {
self.onFulfilledCallbacks.push(() => {
onFuifilled(self.value);
});
self.onRejectedCallbacks.push(() => {
onRejected(self.reason);
});
}
if (this.state === FULFILLED) {
onResolve(this.value)
}
if (this.state === REJECTED) {
onRejected(this.reason)
}
}