Promise
是异步编程的一种解决方案,主要解决异步操作多的时侯出现的问题:
- 异步处理结果顺序不定(如果对处理结果有次序要求的话);
- 为解决上面这个问题,那需嵌套异步处理而且要加判断是否成功,这样会导致代码结构复杂,难以维护;
Promise
的基本使用:
- 实例化
Promise
时,要传入一个函数作为参数,通常写成箭头函数:()=>{}
; - 这个参数又需2个参数,而且也是函数,一个是异步处理成功时调用,另一个是失败时调用,这2个参数通常用resolve和reject命名:
(resolve,reject)=>{}
这个就是Promise
构造函数的参数,这2个函数参数由 JavaScript 引擎提供,不用自己部署,在Promise
里直接调用就是,异步处理的结果作为其2个函数的参数; resolve
函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject
函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
- 然后里面写异步代码,比如ajax请求:
(resolve,reject)=>{异步处理,比如ajax请求}
; then
方法,Promise
实例生成以后,再调用这个Promise
实例的用then
方法,then
方法会等待Promise
里的异步处理结果才会调用的,其可接受两个回调函数作为参数then(success=>{},error=>{})
。第一个回调函数是Promise
对象的状态变为resolved时调用,第二个回调函数是Promise
对象的状态变为rejected时调用。其中,第二个函数是可选的,不一定要提供,或者写到与then
平级的catch
方法里去处理异常。这两个函数都接受Promise对象传出的值作为参数。- 以上总结有7个函数,用逗号分割描述:
Promise构造函数,构造函数的参数也是个函数,resolve函数,reject函数,promise实例的then函数,then的成功函数,then的失败函数(可选)
; - 又可以继续异步操作,不过是在
then
方法里的第1个函数里;
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("ok123");
return;
console.log("....");
}, 1000);
});
console.log("aaa");
p.then(
(result) => console.log(result),
(err) => console.log(err)
);
aaa
ok123
then
方法返回的是一个新的Promise
实例,如果返回的是普通值(非Promise
对象),then
内部也会把结果封装到一个新的Promise
对象,以便then
后还可以调用then
拿到这个普通值,实现链式调用,如果返回的就是Promise
对象,那后面自然还可以用then
链式调用;- 多次的异步操作用
Promise
通常用法是:
- 创建一个函数;
- 在这个函数里先创建一个
Promise
对象并最终返回return
这个Promise
对象; - 回头把异步处理写在这个
Promise
对象里; - 最终呈现的是调用这个函数,返回一个
Promise
对象,接着再调用其then
方法,这时处理了第1个异步操作且结果会在then
里得到,在then
里再调用这个创建的函数并return
出去,这样又返回一个Promise
,又可调用then
方法,如此链式调用下去,再不考虑异常的情况下(then
方法只有一个成功的处理函数作参数):
function getData(url) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("异步处理结果:" + url);
}, Math.ceil(Math.random() * 3) * 1000);
});
}
getData("第1次请求数据")
.then((res) => {
console.log(res);
return getData("第2次请求数据");
})
.then((res) => {
console.log(res);
return getData("第3次请求数据");
})
.then((res) => {
console.log(res);
});
异步处理结果:第1次请求数据
异步处理结果:第2次请求数据
异步处理结果:第3次请求数据
- 通过打印
console.dir(Promise);
,发现then,catch,finally
3个函数是在Promise
的原型对象上,所以所有的Promise
对象都可以调用这3个函数,而all,allSettled,race,reject,resolve
是类方法(有的也称对象方法),只能通过Promise.
调用,实例对象不可调用;
Promise.all()
:并发处理多个任务,只有所有任务都完成才能得到结果;
- 参数是个
Promise
对象数组,Promise.all([p1,p2,p3]).then(res => { })
,返回结果res也是个数组,对应3个Promise
对象的处理结果;
Promise.race()
: 并发处理多个任务,只要有一个任务都完成,就能得到结果;
- 参数是个
Promise
对象数组,Promise.race([p1,p2,p3]).then(res => { })
,返回结果res是3个Promise
对象中,最快处理完的那个的结果;