0%

es6 Promise 复习

Promise 三种状态pending,rejected,fulfilled,只有异步操作的结果能够决定当前的状态,并且状态一旦改变,不能修改。

一般来说,调用resolve或reject以后,Promise 的使命就完成了,后继操作应该放到then方法里面,而不应该直接写在resolve或reject的后面。所以,最好在它们前面加上return语句,这样就不会有意外

1
2
3
4
5
6
7
8
9
 // 立即resolve的Promise在本轮事件循环的末尾执行的。

new Promise((resolve, reject) => {
console.log(1);
return resolve(2);
console.log(3);
}).then((res) => {
console.log(res);
});

then方法返回一个新的Promise,返回的参数作为下一个then方法的函数参数,如果返回的是一个Promise,下一个then会等待Promise状态确定。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
new Promise((resolve, reject) => {
resolve(new Promise((resolve1) => {
setTimeout(() => {
resolve1('resolve 1000');
}, 1000);
}));
}).then((res) => {
console.log(res);
return new Promise((resolve1) => {
setTimeout(() => {
resolve1('resolve 2000');
}, 2000);
});
}).then(res => {
console.log(res);
});

Promise.resolve

Promise.resolve 有四种情况

  • 传入Promise,不做任何处理
  • 传入包含then方法的对象
  • 传入原始值或不包含then方法的对象
  • 不传任何参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

// Promise.resolve

var pp1 = Promise.resolve({ a: '1' });
pp1.then(res => {
console.log(res);
});
// 会调用对象的then方法,结果 先打印hahaah 在打印Promise.resolve+then,这是因为立即resolve的Promise会在本次事件循环末尾调用
var pp2 = Promise.resolve({
a: '2', then(resolve) {
resolve('Promise.resolve+then');
console.log('hahaah');
}
});
pp2.then(res => {
console.log(res);
});

// 如果没有then方法,会直接传入then 方法的回调函数的参数

Promise.try

不管是同步还是异步操作,Promise.try为所有操作提供了统一的处理机制,所以如果想用then方法管理流程,最好都用Promise.try包装一下。

1
2
3
4
5
6
7
8

// Promise.try()
// 实现方法
Promise.try = function (func) {
return new this(function (resolve) {
resolve(func());
});
};

错误处理

promise错误会一直向后传递,如果没有指定catch方法的话,Promise对象抛出的错误不会传递到外层代码。

Promise.all或Promise.race单个Promise没有调用自己的的catch方法,那么会被 Promise.all().catch() 或 Promise.race().catch() 捕获错误。

实现自己的Promise

首先 Promises/A+规范标准 官网地址。

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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
function MyPromise(executor) {
var self = this;
self.status = 'pending';
self.data = null;
self.onResolvedCallback = [];
self.onRejectdCallback = [];

function resolve(value) {
if (value instanceof MyPromise) return value.then(resolve, reject);
// 保证立即调用的resolve后面then方法添加的函数能够执行
setTimeout(() => {
if (self.status === 'pending') {
self.status = 'fulfilled';
self.data = value;
for (var i = 0, len = self.onResolvedCallback.length; i < len; i++) {
self.onResolvedCallback[i](value);
}
}
}, 0);
}

function reject(reason) {
setTimeout(() => {
if (self.status === 'pending') {
self.status = 'reject';
self.data = reason;
for (var i = 0, len = self.onRejectdCallback.length; i < len; i++) {
self.onRejectdCallback[i](reason);
}
}
}, 0);

}

try {
executor(resolve, reject);
} catch (e) {
reject(e);
}

}

function resolvePromise(promise2, x, resolve, reject) {
var then;
var thenCalledOrThrow = false; // 保证 resolve ,reject 只执行一次

if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise!'));
}

if (x instanceof MyPromise) {
if (x.status === 'pending') { //because x could resolved by a Promise Object
x.then(function (v) {
resolvePromise(promise2, v, resolve, reject);
}, reject);
} else { //but if it is resolved, it will never resolved by a Promise Object but a static value;
x.then(resolve, reject);
}
return;
}

if ((x !== null) && ((typeof x === 'object') || (typeof x === 'function'))) {
try {
then = x.then; //because x.then could be a getter
if (typeof then === 'function') {
then.call(x, function rs(y) {
if (thenCalledOrThrow) return;
thenCalledOrThrow = true;
return resolvePromise(promise2, y, resolve, reject);
}, function rj(r) {
if (thenCalledOrThrow) return;
thenCalledOrThrow = true;
return reject(r);
});
} else {
resolve(x);
}
} catch (e) {
if (thenCalledOrThrow) return;
thenCalledOrThrow = true;
return reject(e);
}
} else {
resolve(x);
}
}

MyPromise.prototype.then = function (onResolve, onRejectd) {
var self = this;
var promise2;
onResolve = typeof onResolve === 'function' ? onResolve : function (value) {
/* 解决值的穿透问题 MyPromise().then().then().then(res => {
console.log(res);
});*/
return value;
};
onRejectd = typeof onRejectd === 'function' ? onRejectd : function (reason) {
throw reason;
};

if (self.status === 'fulfilled') {
return promise2 = new MyPromise(function (resolve, reject) {
// 异步调用
setTimeout(() => {
try {
var x = onResolve(self.data);
resolvePromise(promise2, x, resolve, reject);
} catch (reason) {
reject(reason);
}
});
});
}
if (self.status === 'reject') {
return promise2 = new MyPromise(function (resolve, reject) {
setTimeout(() => {
try {
var x = onRejectd(self.data);
resolvePromise(promise2, x, resolve, reject);
} catch (reason) {
reject(reason);
}
});
});
}

// 当pending时,不能确定调用 onResolve,还是 onRejectd
if (self.status === 'pending') {
return promise2 = new MyPromise(function (resolve, reject) {
self.onResolvedCallback.push(function (value) {
try {
var x = onResolve(value);
resolvePromise(promise2, x, resolve, reject);
} catch (r) {
reject(r);
}
});

self.onRejectdCallback.push(function (reason) {
try {
var x = onRejectd(reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
}
};

MyPromise.prototype.catch = function (onRejectd) {
return this.then(null, onRejectd);
};

测试 promise

1
2
npm i -g promises-aplus-tests
promises-aplus-tests Promise.js