实用招式
- 创建一个Promise时,可以是带状态的(Promise.resolve(3));也可以是pending的,将来根据异步结果再去改变状态
- Promise原型方法then的返回值是一个Promise,其状态有then中被执行的回调函数,所执行的结果决定
- async函数返回一个Promise,其状态有async函数执行的结果决定
- await右边多为一个Promise,如果其状态为成功的,await左边可以接受到成功的值;如果失败需要try…catch捕获
纲要
then的返回值(async函数的返回值同理)
1、在被执行的回调函数中return一个Promise
2、return任何一个值,则then函数返回一个成功状态的promise,值为这个值
3、没有return,则then函数返回一个成功状态的Promise,值为undefined
4、报错或者抛错,则then函数返回一个失败状态的Promise,值为失败对象信息
异常穿透
p.then(
value=>{},
//这里没有写失败回调,会自动补充如下代码
//reason=>{throw reason} 或者 reason=> Promise.reject(reason)
).then(
value=>{},
//这里没有写失败回调,会自动补充如下代码
//reason=>{throw reason} 或者 reason=> Promise.reject(reason)
).catch(
reason=>{}
)
如何改变Promise的状态
1、调用resolve,状态变为resolved
2、调用reject,状态变为rejected
3、throw,状态变为rejected
同一个Promise在不同地方同时调用then方法
promise在实现上,会把多个回调函数都保存起来,也就是说都会调用
//同一个promise p,当其状态变为resolved后,1和2都会打印
p.then(
value=> {
console.log(1)
},
reason=> {
}
)
p.then(
value=> {
console.log(2)
},
reason=> {
}
)
自定义Promise
主要实现构造函数和原型上的then方法
// 主线
class Promise{
constructor(excutor){
function resolve(){}
function reject(){}
try{
excutor(resove,reject);
}catch(reason){
reject(reason)
}
}
then(){}
}
// 完整代码
class Promise {
constructor(excutor) {
let self = this;
self.status = 'pending';
self.data = undefined;
self.callbacks = [];
function resolve (value){
if(self.status != 'pending'){
return;
}
self.status = 'resolved';
self.data = value;
//如果有待执行的函数,立刻异步执行回调onResolved
if(self.callbacks.length){
setTimeout(()=>{
self.callbacks.forEach(item=>{
item.onResolved(value);
});
},0);
}
}
function reject(reason){
if(self.status != 'pending'){
return;
}
self.status = 'rejected';
self.data = reason;
if(self.callbacks.length){
setTimeout(()=>{
self.callbacks.forEach((item)=>{
item.onRejected(reason);
});
},0);
}
}
try{
excutor(resolve,reject);
}catch(reason){
reject(reason);
}
}
then(onResolved, onRejected){
//如果当前还是pending状态,就将回调函数保存起来
if(this.status === 'pending'){
this.callbacks.push({onResovle,onRejected});
}else if(this.status === 'resovled'){
//放到队列中执行
setTimeout(()=>{
onResolved(this.data)
},0);
}else{
setTimeout(()=>{
onRejected(this.data);
},0);
}
}
}