一、初始Promise
- Promise不是回调,而是一个内置的构造函数,是程序员自己new调用的
- new Promise的时候,要传入一个回调函数, 他是同步的回调,会立即在主线程上执行,它被称为executor函数
- 每一个Promise实例都有3中状态,分别为初始化(pending)、成功(fulfilled)、失败(rejected)
- 每一个Promise实例在刚被new出来的那一刻,状态都是初始化(pending)
- executor函数会接收到2个参数,它们都是函数,分别用形参:resolve、reject接收
- 调用resolve,会让Promise实例状态变为:成功(fulfilled),同时可以指定成功的value
- 调用reject,会让Promise实例状态变为:失败(rejected),同时可以指定失败的reason
二、Promise基本使用
重要语法
new Promise(executor)
构造函数
Promise.prototype.then
方法基本编码流程
创建Promise的实例对象(pending状态),传入executor函数
在executor中启动异步任务(定时器、ajax请求)
根据异步任务的结果,做不同的处理
如果异步任务成功了:
我们调用
resolve(value)
,让Promise实例对象状态变为成功(fulfilled),同时指定成功的value如果异步任务失败了:
我们调用
reject(reason)
,让Promise实例对象状态变为失败(rejected),同时指定失败的reason通过
then
方法为Promise的实例指定成功、失败的回调函数,来获取成功的value、失败的reason注意:then方法所指定的:成功的回调、失败的回调,都是异步的回调
关于状态的注意点
三个状态
- pending:未确定的 ----> 初始状态
- fulfilled:成功的 ----> 调用resolve()后的状态
- rejected:失败的 ----> 调用reject()后的状态
两种状态改变
- pending -----> fulfilled
- pending -----> rejected
状态只能改变一次!!!
//在executor中 不能同时调用两个,只有第一个会生效! resolve(value); reject(reason);
一个promise指定多个成功 / 失败回调函数,都会调用吗?
会,两个then函数中的回调函数到会放在队列中
三、Promise的API
Promise构造函数:
new Promise(executor){}
- executor函数:是同步执行的,
(resolve,reject)=>{}
- resolve函数:调用resolve将Promise实例内部状态改为成功(fulfilled)
- reject函数:调用reject将Promise实例内部状态改为失败(rejected)
- 说明:excutor函数会在Promise内部立即同步调用,异步代码放在excutor函数中
Promise.prototype.then方法:Promise实例.then(onFulfilled,onRejected)
onFulfilled:成功的回调函数
(value) => {}
onReject:失败的回调函数
(reason) => {}
特别注意(难点):then方法会返回一个新的Promise实例对象
function getPromise(){ return new Promise((resolve,reject)=>{ setTimeOut(()=>{ resolve(1000); },1000); }); } const p = getPromise(); const x = p.then( value=>{}, reason=>{} ); console.log(x); //打印Promise x 说明x为Promise实例对象 console.log(p===x); //最终结果为false
Promise.prototype.catch方法:Promise实例.catch(onRejected)
- onRejected:失败的回调函数
(reason) => {}
- 说明:catch方法是then方法的语法糖,相当于:then(undefined,onRejected)
Promise.resolve方法:
Promise.resolve(value)
说明:用于快速放回一个状态为fulfilled或rejected的Promise实例对象
备注:value的值可能是:(1)非Promise值 (2)Promise值
//value为100 [] {} 等非Promise值 最终结果都是fulfilled //value为Promise值,那么最终结果就是Promise值的结果 const p0 = Promise.reject(1000); //如果vallue为Promise值,那么p状态和value就是p0的状态和value const p = Promise.resolve(p0); p.then( (value)=>{ console.log("成功了",value); }, (reason)=>{ console.log("失败了",reason); } );
Promise.reject方法:
Promise.reject(reason)
说明:用于快速放回一个状态必为rejected的Promise实例对象
const p0 = Promise.resolve(100); //当p的reason是Promise值,当他的状态也是rejected,不会等于p0的状态 //p的reason 就是p0的实例 const p = Promise.reject(p0); p.then( (value) => { console.log('成功了',value); }, (reason) => { console.log('失败了',reason); } )
Promise.all方法:
Promise.all(promiseArr)
promiseArr:包含n个Promise实例的数组
说明:返回一个新的Promise实例,只有所有的promise都成功才成功,只要有一个失败了就直接失败
const p1 = Promise.resolve(100); const p2 = Promise.resolve(100); const p3 = Promise.resolve(100); //如果参数中的Promise状态都为fulfilled 那么Promise.all 返回的实例也是fulfilled //value 为一个数组,为参数中Promise实例的value const x = Promise.all([p1,p2,p3]); x.then( (value) => { console.log('成功了!',value); }, (reason) => { console.log('失败了!',reason); } );
//当Promise参数数组中 有一个Promise实例的状态为rejected 那么Promise.all 的 状态也为 rejected
//reason 等于执行最快的Promise且状态为rejected的reason
//打印结果 失败了! b
const p1 = Promise.resolve(‘a’);
const p2 = new Promise((resolve,reject) => {
setTimeout(() => {
reject(‘b’);
}, 1000);
});
const p3 = new Promise((resolve,reject) => {
setTimeout(() => {
reject(‘c’);
}, 2000);
});const x = Promise.all([p1,p2,p3]);
x.then(
(value) => {
console.log(‘成功了!’,value);
},
(reason) => {
console.log(‘失败了!’,reason);
}
);
Promise.race方法:
Promise.race(promiseArr)
- promiseArr:包含n个Promise实例的数组
- 说明:返回一个新的Promise实例,成功还是失败?以最先出结果的promise为准
四、Promise的链式调用
Prmoise实例.then() 返回的是一个【新的Promise实例】,它的值和状态由什么决定
- 简单表达:由then()所指定的回调函数执行的结果决定
- 详细表达:
- 如果then所指定的回调返回的是非Promise值a
- 那么【新Promise实例】状态为:成功(fulfilled),成功的value为a
- 如果then所指定的回调返回的是一个Promise实例p
- 那么【新Promise实例】的状态、值,都与p一致
- 如果then所指定的回调抛出异常:
- 那么【新Promise实例】的状态为rejected,reason为抛出的那个异常
五、如何中断链式调用
function sendAjax(url){
return new Promise((resolve,reject) => {
if(true){
resolve('成功了');
}else{
reject('失败了');
}
});
}
sendAjax('http://localhost:8080/xxx')
.then(
value => {
console.log('成功了',value);
return sendAjax('http://localhost:8080/xxx');
},
reason => {
console.log('失败了',reason);
//如果失败终止链式调用
//原理 , 因为该Promsise实例是pending状态,所有后面then中的resolve\reject回调函数都不会执行
return new Promise((resolve,reject) => {});
}
)
.then(
value => {
console.log('成功了',value);
},
reason => {
console.log('失败了',reason);
}
)
六、async和await修饰符
- async修饰的函数
- 函数的返回值为promise对象
- Promise实例的结果由async函数执行的返回值决定
- await表达式
- await右侧的表达式一般为Promise实例对象,但也可以是其他的值。
- 如果表达式是promise对象,await后的返回值是promise实例成功回调的值
- 如果表达式是其他值,直接将此值作为await的返回值
- 注意:
- await必须写在async函数中,但async函数中可以没有await
- 如果await的promise失败了,就会抛出异常,需要通过try…catch来捕获处理
七、宏队列、微队列
宏队列和微队列只存在异步回调中
规则:每次要执行宏队列里的一个任务之前,先看微队列里是否有待执行的微任务
- 如果由,先执行微任务
- 如果没有,按照宏队列里任务的顺序,依次执行
- 顺序规则:先进先出