简介
Promise简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。
Promise有三种状态:pending
、fulfilled
、rejected
Promise对象初始化时状态为:pending
(进行中)
调用resolve方法时,Promise的状态由pending
变为fulfilled
调用rejected方法时,Promise的状态由pending
变为rejected
1、 Promise对象的状态不受外界影响,只有异步操作的结果可以决定当前时哪一种状态,任何其他操作都无法改变这个状态。
2、 一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从
pending
变为fulfilled
和从pending
变为rejected
。
使用
简单的初始化一个Promise
1 | const promise = new Promise((resolve) => { |
上面初始化了一个Promise对象,并创建了一个异步操作:在两秒后调用resolve方法。这里仅仅是初始化了这个对象,并没有调用。继续调用这个promise对象
1 | const promise = new Promise((resolve) => { |
当执行代码的时候,控制台在两秒钟后打印出了“延迟2s回调”,也就是说在上面初始化Promise的resolve里面的参数回调到了下面then方法中的data参数中。简单来说就是then里面的函数,会传递到Promise中并由resolve来控制这个函数的执行时间以及执行所需要的参数并回调。
上述代码的执行过程就是Promise内部状态由pending
变为fulfilled
。
Promise还有从pending
变为rejected
的过程。
1 | const promise = new Promise((resolve, reject) => { |
在Promise中初始化了一个简单逻辑,两秒之后获得一个随机数字,该数字大于5的时候调用resolve方法,反之则调用reject方法。由上面的例子可以得知,当数字大于5的时候会在then中打印。那么当数字小于5的时候,则会在catch中打印改数字。
简单总结下来,resolve方法回调至then中,reject方法回调至catch中。
那么可以借用Promise的特点,简单的封装一个网络请求。使用resolve
和reject
分别包装正常返回和异常返回的值和信息。
1 | const promise = new Promise((resolve, reject) => { |
链式调用
通过上面的例子Promise可以理解为是一个类似延迟加载的异步回调函数,那么其实也可以用普通的方法实现Promise的功能
1 | myPromise = (callback) => { |
它也会和Promise拥有同样的效果。那Promise到底能实现什么不可替代的功能呢?
假如有许多的异步操作需要执行,比如连续的三个请求,每一次请求都需要从前一个请求中获取参数,那么它的写法如下
1 | fetch(url1).then((data1) => { |
虽然可以实现需求,然是代码看起来并不那么友好,它庞大的层级结构使之无法轻易被修改。如果要是需要在第二个请求和第三个请求中再加入一些异步操作,那么将是不可修改的,这被称为回调地狱(Callback hell)。
使用Promise即可解决上述问题,Promise的优势在于,可以在then方法中继续写Promise对象并返回,然后继续调用then来进行回调操作。也就是说可以一直return一个Promise对象,可以一直在在后面调用then方法。如果使用Promise后上述的需求可以写为
1 | // 分别将三个请求包装为函数 |
只需要在then中调用下一个Promise,上一个Promise中回调的数据即可传递下去。
关于回调地狱(Callback hell)的问题也可以使用async/await解决,类似的代码如下
1
2
3
4
5
6
7
8
9
10
11 task() async {
try{
String id = await request1();
String userInfo = await request2();
await request3();
//执行接下来的操作
} catch(e){
//错误处理
print(e);
}
}
相关API
all
Promise.all方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。
1 | const p = Promise.all([promise1, promise2, promise3]); |
p
的状态由promise1
、promise2
、promise3
决定,分成两种情况。
(1)只有promise1
、promise2
、promise3
的状态都变成fulfilled
,p
的状态才会变成fulfilled
,此时promise1
、promise2
、promise3
的返回值组成一个数组,传递给p
的回调函数。
(2)只要promise1
、promise2
、promise3
之中有一个被rejected
,p
的状态就变成rejected
,此时第一个被reject
的实例的返回值,会传递给p
的回调函数。
注意,如果作为参数的 promise 实例,自己定义了
catch
方法,那么它一旦被rejected
,并不会触发Promise.all()
的catch
方法。
race
Promise.race方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。
1 | const p = Promise.race([promise1, promise2, promise3]); |
上面代码中,只要有任何一个promise改变状态,那么p的状态也会跟着改变。也就是说最快改变状态的promise会让其他promise不会回调。
可以通过这个方法来完成一个请求超时功能
1 | const p = Promise.race([ |
即当5s内请求没有返回结果,就返回请求超时。