目录
概念
什么是Promise
Promise是一个构造函数,其原型上有then、catch方法,还有resolve、reject等静态方法;
通过创建Promise实例,可以调用Promise.prototype上的then、ctach方法。
Promise与异步编程的关系
Promise是异步编程的一种解决方案;
Promise(里面会保存异步操作的结果)是一个对象,它可以获取异步操作的消息,并提供统一的API,各种异步操作都可以用同样的方法进行处理。
总结:Promise 是一个由异步函数返回的可以向我们指示当前操作所处的状态的对象。
Promise的作用与用法
作用
通知异步操作结束,resolve与reject,这两个函数会告诉异步操作的状态;
在实例化Promise时要传入resolve和reject两个函数做参数,当异步任务顺利完成且返回结果值时,会调用resolve函数,而当异步任务失败且返回失败原因时,会调用reject函数。
用法(包括应用)
Promise的几种状态
1.pending:初始状态,进行中
2.fulfilled:成功完成
3.rejected:失败
处于初始状态(pending)的Promise,最终要么成功(fulfilled )要么失败(rejected ),无论成功还是失败,都要通过then方法调用相关处理程序。
基本用法举例
let p=new Promise((resolve,reject)=>{
setTimeout(function(){
//resolve('成功'),传的参数会作为then函数中成功函数的实参
reject('失败')
},1000)
});
p.then((data)=>{
console.log('success'+data)
},(err)=>{
console.log('fail'+err)//最终结果是fail失败
})
简单示例
function timeout(ms){
return new Promise((resolve,reject)=>{
setTimeout(resolve,ms,'done');
});
}
timeout(5000).then((value)=>{
console.log(value);
});
console.log('this going on');
在这段代码中,timeout方法返回了一个Promise实例,表示指定时间(ms)后才会发生的结果,Promise实例的状态变成fulfilled,就会触发then方法绑定的回调函数;
此处的'done'会作为参数传递给resolve,作为当前Promise对象成功时的值。
Promise新建后会立即执行
举例:
let p=new Promise(function(resolve,reject){
console.log('Promise');
resolve();
});
p.then(function(){
console.log('resolved');
});
console.log('Hi');
输出顺序:Promise Hi resolved(当所有同步任务执行完后才会执行then方法指定的回调函数)
then( )方法
举例1:
let p1=new Promise((resolve,reject)=>{
setTimeout(()=>{//宏队列
resolve("ok");//4
},2000);
});
console.log("p1",p1);//1
let p2=p1.then((value)=>{//进入微队列
console.log("p1",p1,value);//5
return value.toUpperCase();
});
console.log("p2",p2);//2
let p3=p2.then((value)=>{//进入微队列
console.log("p2",p1,value);//6
});
console.log("p3",p3);//3
运行结果:
分析:
会按照上述注释所标注的顺序来执行;
p1的setTimeout先进入了宏队列,故p1、p2、p3都会在pending状态,当同步任务完成、时间到了之后,第三行的resolve函数执行,传入‘ok’参数,p1影响p2,p2影响p3,因此后续可以在运行结果中看到,Promise结果是ok。
举例2:
let p1=new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("ok");
},2000);
});
let p2=p1.then((value)=>{
console.log(`Get value ${value} from p1`);
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(value.toUpperCase());
},1000);
});
});
let p3=p2.then((value)=>{
console.log(`Get value ${value} from p1`);
});
运行结果:
原理同上,不多做解释
resolve( )与reject( )方法
resolve( )会返回成功的Promise对象,reject( )会返回失败的Promise对象
Promise.resolve("hello wolrd").then((result)=>console.log(result));
let p=new Promise((resolve)=>resolve("foo"));
Promise.resolve(p).then((result)=>console.log(result));//相当于直接调用了p
运行结果:
hello world
foo
注:当传入的参数是一个Promise实例时,该实例将会被直接返回;否则,将创建一个新的Promise对象,并将传入的参数作为Promise对象的fulfilled值。
而reject( )方法表示抛出错误,用于返回一个rejected状态的Promise实例,但一般情况下没有太大用处。
注意:调用resolve和reject并不会终结Promise的参数函数的执行;
调用resolve和reject后,Promise的使命就完成了,后续操作会放在then中,故最好在它们前面加上return。
链式调用与catch( )方法
链式调用:Promise实例可以链式的then调用,如果需要就可以一直调用下去。
let p1=new Promise((resolve,reject)=>{
setTimeout(()=>{
let t=true;
if(t){
resolve("success");
}else{
reject("failed");
}
},1000);
});
p1.then((r)=>{
console.log(r);
return r+"1";
}).then((r)=>{
console.log(r);
return r+"2";
}).then((r)=>{
console.log(r);
});
运行结果:
(依次向下执行)
catch()方法用于捕获与处理错误,一般不要在then方法中定义rejected状态的回调函数,而应该总是使用catch方法。
Promise.reject(new Error("a special error"))
.catch((err)=>{
console.log(err.message);
return "done";
})
.then((value)=>{
console.log(value);
});
运行结果:
(catch方法捕获到了错误)
catch( )可用于终止Promise链,避免链条中rejection抛出错误到全局。
new Promise( ( resolve, reject) =>{
console.log ( "in Promise" );//会执行
resolve();
}).then( () => {
throw new Error( "then Error" );//手动报错
console.log ( "then " );//不会执行
} ).then( ()=>{
console.log ( "then continue" );//不会执行
} ).catch((err)=> {
console.log ( "catch error: " +err.message ) ;//会执行
});
all( )方法
需要将多个Promise任务一起执行时,可以使用;
Promise.all()实参是所有Promise实例的字面量组成的数组,,执行完毕的结果时所有输出结果组成的数组。
var p1=new Promise((res,rej)=>{
setTimeout(()=>{
res("p1");
},1000);
});
var p2=new Promise((res,rej)=>{
setTimeout(()=>{
res("p2");
},2000);
});
var p3=new Promise((res,rej)=>{
setTimeout(()=>{
res("p3");
},3000);
});
Promise.all([p1,p2,p3]).then((r)=>{
console.log(r);
}).catch((err)=>console.log(err.message));
运行结果:
注意:array(3)["p1","p2","p3"]是按照数组的顺序输出;若为[p3,p2,p1]则会输出[p3,p2,p1]
且若数组中有一个是rejected,则最后结果输出undefined。
race( )方法
Promise.race(iterable),iterable是包含了多个promise对象的可迭代数据结构,如数组;
该方法返回一个promise;
一旦迭代器中的某个promise解决或拒绝,返回的promise就会解决或拒绝。
const p1=new Promise((resolve,reject)=>{
setTimeout(resolve,500,"one");
});
const p2=new Promise((resolve, reject)=>{
setTimeout(resolve,100,"two");
});
const p3=new Promise((resolve, reject)=>{
setTimeout(reject,200,new Error("some thing is wrong"));
});
Promise.race([promise1,promise2,promise3])
.then((vaLue)=>{
console.log(value);
})
.catch((err) =>{
console.log(err.message);
})
最终会输出two;故谁最先执行完,就以谁为准执行回调,第一个完成的promise就是最终的结果状态。
async/await的作用与用法
async
关键字定义的函数,会使异步操作变得更加方便;
async函数返回的Promise对象会运行执行(resolve)异步函数的返回结果,函数中有返回值,则相当于执行了 Promise.resolve(返回值)
函数,没有返回值,则相当于执行了 Promise.resolve()
函数;
或者如果异步函数抛出异常的话会运行拒绝(reject) 。
async function f() {
return "12345";
}
f().then((r) => {
console.log(r);
});
await
是async wait的简写,意为等待异步执行完成;
await必须在async定义的函数中,不可以单独使用;
该指令会暂停异步函数的执行,并等待Promise执行,然后继续执行异步函数,并返回结果,如果等待的不是promise对象,则返回该值本身。
async function asyncFunc(){
console.log ( "1" );
await
Promise.resolve().then(()=>console.log ( "5"));
console.log ( "2" );
return "6" ;
}
console.log("3");
asyncFunc().then(( res)=>console.log ( res ) ) ;
console.log("4");
运行结果:314526