0%

Promise

What is Promise

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let p = new Promise((resolve, reject) => {
// 做一些事情
// 然后在某些条件下resolve,或者reject
if (/* 条件随便写^_^ */) {
resolve()
} else {
reject()
}
})

p.then(() => {
// 如果p的状态被resolve了,就进入这里
}, () => {
// 如果p的状态被reject
})

构造实例

  • 构造函数接受一个函数作为参数
  • 调用构造函数得到实例p的同时,作为参数的函数会立即执行
  • 参数函数接受两个回调函数参数resolve和reject
  • 在参数函数被执行的过程中,如果在其内部调用resolve,会将p的状态变成fulfilled,或者调用reject,会将p的状态变成rejected.

调用.then

  • 调用.then可以为实例p注册两种状态回调函数
  • 当实例p的状态为fulfilled,会触发第一个函数执行
  • 当实例p的状态为rejected,则触发第二个函数执行
  • then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。

总结

  • 将异步过程转化成promise对象
  • 对象有3种状态
  • 通过.then注册状态的回调
  • 已完成的状态能触发回调

How to use Promise

3种状态

首先,promise实例有三种状态:

  • pending(待定)
  • fulfilled(已执行)
  • rejected(已拒绝)

fulfilled和rejected有可以说是已成功和已失败,这两种状态又归为已完成状态

resolvereject

调用resolve和reject能将分别将promise实例的状态变成fulfilled和rejected,只有状态变成已完成(即fulfilled和rejected之一),才能触发状态的回调

promise的内容分为构造函数、实例方法和静态方法

1个构造函数: new Promise

  • new Promise能将一个异步过程转化成promise对象。先有了promise对象,然后才有promise编程方式。

2个实例方法:.then 和 .catch

  • .then用于为promise对象的状态注册回调函数。它会返回一个promise对象,所以可以进行链式调用,也就是.then后面可以继续.then。在注册的状态回调函数中,可以通过return语句改变.then返回的promise对象的状态,以及向后面.then注册的状态回调传递数据;也可以不使用return语句,那样默认就是将返回的promise对象resolve。
  • .catch用于注册rejected状态的回调函数,同时该回调也是程序出错的回调,即如果前面的程序运行过程中出错,也会进入执行该回调函数。同.then一样,也会返回新的promise对象。

4个静态方法:Promise.all、Promise.race、Promise.resolve和Promise.reject

调用Promise.resolve会返回一个状态为fulfilled状态的promise对象,参数会作为数据传递给后面的状态回调函数; Promise.reject与Promise.resolve同理,区别在于返回的promise对象状态为rejected

1
2
3
4
5
6
7
8
9
10
11
12
13
Promise.resolve(1);

// 等价于

new Promise((resolve) => resolve(1));

Promise.reject(new Error("BOOM"))

// 等价于

new Promise((resolve, reject)
=> reject(new Error("BOOM")));

Practice

题目:红灯三秒亮一次,绿灯一秒亮一次,黄灯2秒亮一次;如何让三个灯不断交替重复亮灯?

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
function red(){
console.log('red');
}

function green(){
console.log('green');
}

function yellow(){
console.log('yellow')
}

let light = (fn, timer) => new Promise( resolve => {
setTimeout(function() {
fn();
resolve();
}, timer)
});

function start(times) {
if (!times) {
return
}

times--
Promise.resolve()
.then(() => light(red, 3000))
.then(() => light(green, 1000))
.then(() => light(yellow, 2000))
.then(() => start(times))
}

start(3)

async/await

async

async关键字的意思很简单,就是函数返回的是一个promise

1
2
3
4
5
6
async function f() {
return 1;
}
f().then((res) => {
console.log(res)
}) // 1

async函数会返回一个promise对象,如果function中返回的是一个值,async直接会用Promise.resolve()包裹一下返回。

await

[return_value] = await expression;

关键词await是等待的意思,那么他在等什么呢? 等的是一个表达式,那么表达式,可以是一个常量,变量,promise,函数等。

await操作符等的是一个返回的结果,那么如果是同步的情况,那就直接返回了。 异步的情况下,await会阻塞整一个流程,直到结果返回之后,才会继续下面的代码。

1
2
3
4
5
6
7
8
9
10
11
function getProvinces () {
return new Promise(resolve => {
setTimeout(resolve, 1000)
})
}
async function asyncFn () {
await getProvinces()
console.log('hello async')
}

asyncFn()

上面代码先定义了一个获取省份数据的getProvinces函数,其中用setTimeout模拟数据请求的异步操作。当我们在asyncFn 函数前面使用关键字 async 就表明该函数内存在异步操作。当遇到 await 关键字时,会等待异步操作完成后再接着执行接下去的代码。所以代码的执行结果为等待1000毫秒之后才会在控制台中打印出 'hello async'。

Reference

  • https://zhuanlan.zhihu.com/p/26523836
  • https://juejin.im/post/5d9e8539f265da5b8a515e63
  • https://juejin.im/post/5c553b71f265da2d8532b351