结合bilibili和小米和阿里的面试题中出现的与Promise对象相关的问题自己试着做了一些回答,涉及的有以下几个问题。
- 详述Promise的异步机制?
- Promise有几种状态?
- Promise如何满足多个异步进程的同步顺序?
- Promise.all的用法
- 如何让Promise.all在抛出异常后依然有效?
- Promise.all与Promise.race的区别?应用场景?
1.Promise的异步机制
1.通过Promise
对象可以获取异步操作的消息。Promise
构造函数接受一个函数作为参数,该函数的两个参数又分别是resolve
和reject
。resolve
函数的作用是将Promise
对象的状态从未完成变成完成,在异步操作成功时调用,并且将异步操作的结果作为参数传递出去。reject
函数是将Promise
对象的状态从未完成变成失败,在异步操作失败时调用,并将异步操作报出的错误作为参数传递出去。
2.Promise
实例生成以后使用then
方法分别指定resolved
和rejected
状态的回调函数。Promise
实例的状态变为resolved
,就会触发then
方法绑定的回调函数。有多个异步任务就可以写多个then
方法。这时前一个回调函数有可能返回的还是一个promise
对象(即有异步操作),这时后一个回调函数就会等待该Promise
对象的状态发生变化,才会被调用。
2.Promise的状态
Promise
有三种状态,分别是:
pending:
进行中fulfilled
:已成功rejected
:已失败
注意:只有异步操作的结果可以决定当前是哪一种状态,其他任何操作都无法改变这个状态。
3.Promise如何满足多个异步进程的同步顺序
可以使用then方法链式调用。
采用链式的then
,可以指定一组按照次序调用的回调函数,这时,前一个回调函数有可能返回的还是一个promise
对象(即有异步操作),这时后一个回调函数就会等待该Promise
对象的状态发生变化,才会被调用。这就满足了多个异步进程的从上到下执行的同步顺序。
4.Promise.all的用法
Promise.all
方法用于将多个 Promise
实例,包装成一个新的 Promise
实例。
语法:
const p = Promise.all([p1, p2, p3]);
上面p1,p2,p3都是promise
实例,只有所有实例p1,p2,p3的状态都变为fulfilled
,p的状态才会变成fulfilled
。
此时,实例p1
,p2,
p3
的返回值组成一个数组,传递给p的回调函数。
例如:如果有多个异步请求,但是最终用户想要得到的结果是多个异步结果合并到一起的完整结果。代码如下:
let p1 = new Promise((resolve, reject) => {
resolve('p1成功')
})
let p2 = new Promise((resolve, reject) => {
resolve('p2成功')
})
let p3 = new Pomise((resolve,reject)=>{
resolve('p3成功')
})
Promise.all([p1, p2,p3]).then((res) => {
console.log(res) //['p1成功', 'p2成功',p3成功]
}).catch((error) => {
console.log(error)
})
5.如何让Promise.all在抛出异常后依然有效
方法:给每个作为Promise.all
参数的Promise
实例定义catch
方法。
那么某个promise
实例一旦被rejected
,就会进入自己的catch
方法,该实例执行完catch
方法后,也会变成resolved
。那么就不会触发Promise.all
的catch
方法,Promise.all
在抛出异常后也依然有效。
例如:
const p1 = new Promise((resolve, reject) => {
resolve('hello');
})
.then(result => result)
.catch(e => e);
const p2 = new Promise((resolve, reject) => {
throw new Error('报错了');
})
.then(result => result)
.catch(e => e);
Promise.all([p1, p2])
.then(result => console.log(result))
.catch(e => console.log(e));
// ["hello", Error: 报错了]
上面代码中,p1会resolved
,p2首先会rejected
,但是p2有自己的catch
方法,该方法返回的是一个新的 Promise
实例,p2指向的实际上是这个实例。该实例执行完catch
方法后,也会变成resolved
,导致Promise.all()
方法参数里面的两个实例都会resolved
,因此会调用then
方法指定的回调函数,而不会调用catch
方法指定的回调函数。
如果p2没有自己的catch
方法,就会调用Promise.all()
的catch
方法。
详细请参考阮一峰老师的es6文章。
6.Promise.all与Promise.race的区别?应用场景?
Promise.race方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。
const p = Promise.race([p1, p2, p3]);
只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。
Promise.all与Promise.race的区别:
-
Promise.all
:返回一个promise
对象,接收的多个promise
实例对象都成功了,Promise.all
返回的promise
对象才会成功。应用场景:一个功能的数据,要有多个ajax请求拼接才能得到最终的数据。
-
Promise.race
:返回一个promise
对象,这个promise
对象只会取决于第一个完成的promise
实例的结果。应用场景:通过2个方法拿数据,哪个方法数据拿的快,就先拿哪个方法的数据。