简介
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内请求没有返回结果,就返回请求超时。