API结构图
术语
promise的执行过程
了解Promise诞生的历史背景
学会使用Promise解决异步回调带来的问题
掌握Promise的进阶用法
异步操作的常见语法
1 | document.getElementById('start').addEventListener('click',start,false); |
有了Node.js之后
对异步的依赖进一步加剧了……
无阻塞高并发
Promise详解
1 | new Promise( |
Promise实例一经创建,执行器立即执行
简单实例
1 | console.log("here we go"); |
两步执行的范例
1 | console.log("here we go"); |
对已完成的Promise执行then
1 | console.log("start"); |
不管promise前面的状态是否完成,都会按它的队列去执行
then里不返回Promise
1 | console.log("start"); |
引出.then()
.then()接受两个函数作为参数,分别代表fulfilled和rejected
.then()返回一个新的Promise实例,所以它可以链式调用
当前面的Promise状态改变时,.then()根据其最终状态,选择特定的状态响应函数执行
状态响应函数可以返回新的Promise,或其他值
如果返回新的Promise,那么下一级.then()会在新Promise状态改变后执行
-
.then()里有.then()的情况
因为.then()返回的还是Promise实例。
会等里面的.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
61
62
63
64
65
66
67
68
69
70
71
72
73
74console.log("start");
let promise = new Promise(resolve => {
console.log("step1");
setTimeout(() => {
resolve("100");
}, 1000);
})
.then(value => {
return new Promise(resolve => {
console.log("Step 1-1");
setTimeout(() => {
resolve(110);
}, 1000);
})
.then(value => {
console.log("Step 1-2");
return value;
})
.then(value => {
console.log("Step 1-3");
return value;
});
})
.then(value => {
console.log(value);
console.log("Step 2");
});
start
step1
Step 1-1
Step 1-2
Step 1-3
110
Step 2
一样的效果可以这样改
console.log("start");
let promise = new Promise(resolve => {
console.log("step1");
setTimeout(() => {
resolve("100");
}, 1000);
})
.then(value => {
return new Promise(resolve => {
console.log("Step 1-1");
setTimeout(() => {
resolve(110);
}, 1000);
});
})
.then(value => {
console.log("Step 1-2");
return value;
})
.then(value => {
console.log("Step 1-3");
return value;
})
.then(value => {
console.log(value);
console.log("Step 2");
});
start
step1
Step 1-1
Step 1-2
Step 1-3
110
Step 2
问题:下面的四种Promise的区别是什么
问题一
问题二
问题三(比较有欺骗性)doSomethingElse()也是一个promise
问题四
错误处理
1 | console.log("start"); |
错误处理的两种做法:
- reject(‘错误信息’).then(null,message=>{})
1 | console.log("start"); |
throw new Error(‘错误信息’).catch(message=>{})
1
2
3
4
5
6
7
8
9
10
11
12console.log("start");
new Promise((resolve, reject) => {
setTimeout(() => {
throw new Error("bye");
}, 2000);
})
.then(value => {
console.log(value + " world");
})
.then(error => {
console.log("Error: ", error, error.message);
});推荐使用第二种,更加清晰好读,并且可以捕获前面的错误
强烈建议在所有队列最后都加上.catch(),以避免漏掉错误处理造成意想不到的问题
Promise.all
Promise.resolve
promise then里面的值,都是resolve来传递改变的
1 | console.log("start"); |
Promise.reject
目前位置就是提示报错,没有别的作用
1 | let promise = Promise.reject("something wrong"); |
Promise.race
它有任意一个完成就算完成了和promise.all的区别
1 | let p1 = new Promise(resolve => { |
常见用法:
把异步操作和定时器放在一起,如果定时器先触发,就认为超时,告知用户
把回掉包装成Promise
可读性更好
返回的结果可以加入任何promise队列
手撕promise源码
1 |
|
Promise 的状态
一个 Promise 的当前状态> 必须为以下三种状态中的一种:等待态(Pending)、执行态(Fulfilled)和拒绝态(Rejected)。
等待态(Pending)
处于等待态时,promise 需满足:可以
迁移至执行态或拒绝态
执行态(Fulfilled)
处于执行态时,promise 需满足:不能
迁移至其他任何状态,必须拥有一个不可变
的终值
拒绝态(Rejected)
处于拒绝态时,promise 需满足:不能
迁移至其他任何状态,必须拥有一个不可变
的据因
这里的不可变指的是恒等(即可用 > ===
判断相等),而不是意味着更深层次的不可变( 指当 value 或 reason 不是> 基本值时,只要求其引用地址相等,但属性值可被更改)。