本文已参与[新人创作礼]活动,一起开启掘金创作之路。
Promise对象
Promise是一个对象,从它可获取异步操作的一些信息。
基本的知识在菜鸟教程中可学习:www.runoob.com/w3cnote/es6…
通过new Promise() 即可构造一个Promise实例,这个构造函数接收一个函数,函数接收两个参数:resolve和reject,代表改变实例的状态到已完成(resolve)或已拒绝(reject)。
相关API
这里定义fn1和fn2,简单介绍了API的使用。
const fn1 = new Promise((resolve,reject)=>{
setTimeout(()=>{
let num = 'fn1';
// 内部定义成功时调用
resolve(num);
// 内部定义失败时调用
reject('err-fn1');
},200)
})
const fn2 = new Promise((resolve,reject)=>{
setTimeout(()=>{
// 内部定义成功时调用
resolve('fn2');
// 内部定义失败时调用
reject('err-fn2');
},100)
})
fn1.then((res1)=>{
console.log(res1);
},(err1)=>{
console.log(err1)
})
fn2.then((res2)=>{
console.log(res2);
},(err2)=>{
console.log(err2);
})
Promise构造函数
Promise(excutor){}
1.excutor函数:执行器(resolve,reject)=>{}
2.resolve函数:内部定义成功时我们调用的函数 (value)=>{}
3.reject函数:内部定义失败时我们调用的函数 (reason)=>{}
Promise.prototype.then方法
(onResolved,onRejected)
1.onResolve函数:成功的回调函数 (value)=>{}
2.onReject函数:失败的回调函数 (reason)=>{}
指定用于得到成功value的成功回调和用于得到失败reason的失败回调,返回一个新的Promise对象。
Promise.prototype.catch方法
(onReject)
1.onReject函数:失败的回调函数 (reason)=>{}
catch为then的语法糖,相当于:then(undefined,onRejected)
then和catch属于Promise实例对象。
Promise.prototype.finally()
finally()方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的。
Promise方法
这里面的方法属于Promise函数对象的。
Promise.resolve
Promise.resolve方法:(value)=>{}
value 成功的数据或Promise对象
Promise.resolve返回一个成功或失败的Promise对象。
作用:快速得到一个Promise对象,可以封装一个值,将值转化为一个promise对象。
Promise.resolve将值转换为Promise对象:
let fn = Promise.resolve(999);
console.log(fn);
若传入的参数为非Promise对象的值,则返回结果为成功Promise对象。 若传入的参数为Promise对象,则参数的结果决定resolve的结果。
参数Promise对象成功:
// 若传入的参数为非Promise对象的值,则返回结果为成功Promise对象。
// 若传入的参数为Promise对象,则参数的结果决定resolve的结果。
let fn = Promise.resolve(new Promise((resolve,reject)=>{
// 参数成功的结果
resolve('success');
console.log(resolve,reject);
}));
console.log(fn);
参数Promise对象失败:
// 若传入的参数为非Promise对象的值,则返回结果为成功Promise对象。
// 若传入的参数为Promise对象,则参数的结果决定resolve的结果。
let fn = Promise.resolve(new Promise((resolve,reject)=>{
// 参数成功的结果
reject('err');
console.log(resolve,reject);
}));
console.log(fn);
fn.catch((err)=>{
console.log(err);
})
Promise.reject
Promise.reject 方法:(reson)=>{}
reson 失败的原因
Promise.reject返回一个失败的Promise对象。
Promise.reject将值转换为Promise对象:
let fn = Promise.reject(999);
console.log(fn);
fn.catch((err)=>{
console.log(err);
})
不管传入的参数为非Promise对象还是Promise对象,则返回结果都为失败的Promise对象。
参数Promise对象成功:
let fn = Promise.reject(new Promise((resolve,reject)=>{
// 参数成功的结果,但是Promise.reject依旧返回失败的Promise对象。
resolve('success');
console.log(resolve,reject);
}));
console.log(fn);
fn.catch((err)=>{
console.log(err);
})
返回结果是失败的Promise对象:
参数Promise对象失败:
let fn = Promise.reject(new Promise((resolve,reject)=>{
// 参数失败的结果,Promise.reject依旧返回失败的Promise对象。
reject('err');
console.log(resolve,reject);
}));
console.log(fn);
fn.catch((err)=>{
console.log(err);
})
返回结果是失败的Promise对象:
Promise.all
Promise.all方法:(promises)=>{}
promises:包含n个Promise的数组
返回一个新的Promise,只有所有的Promise成功才成功,只要有一个失败了就直接失败。
成功的结果是每一个Promise对象成功结果组成的数组,失败的结果为失败的Promise对象失败的结果。
全部成功
let fn = new Promise((resolve,reject)=>{
resolve('success');
console.log(resolve,reject);
});
let fn1 = Promise.resolve('success-1');
let fn2 = Promise.resolve('success-2');
const result = Promise.all([fn,fn1,fn2])
console.log(result);
失败一个:
let fn = new Promise((resolve,reject)=>{
resolve('success');
console.log(resolve,reject);
});
let fn1 = Promise.resolve('success-1');
let fn2 = Promise.reject('err');
const result = Promise.all([fn,fn1,fn2])
console.log(result);
result.catch((err)=>{
console.log(err);
})
失败多个,只返回第一个错误的信息:
let fn = new Promise((resolve,reject)=>{
resolve('success');
console.log(resolve,reject);
});
let fn1 = Promise.reject('err-1');
let fn2 = Promise.reject('err-2');
const result = Promise.all([fn,fn1,fn2])
console.log(result);
result.catch((err)=>{
console.log(err);
})
Promise.race
Promise.race方法:(promises)=>{}
promises:包含n个Promise的数组
返回一个新的Promise,第一个完成的promise的结果状态就是最终的结果状态。
let fn = new Promise((resolve,reject)=>{
resolve('success');
console.log(resolve,reject);
});
let fn1 = Promise.reject('err-1');
let fn2 = Promise.reject('err-2');
const result = Promise.race([fn,fn1,fn2])
console.log(result);
let fn = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('success');
console.log(resolve,reject);
},100)
});
let fn1 = Promise.resolve('success-1');
let fn2 = Promise.resolve('success-2');
const result = Promise.race([fn,fn1,fn2])
console.log(result);
改变Promise对象状态的方式
改变Promise对象状态有三种方式:1.resolve 函数。2.reject 函数。3.抛出错误。
// 改变Promise对象状态的方式
let fn = new Promise((resolve,reject)=>{
console.log(resolve,reject);
// 1.resolve 函数 pending => fulfilled(resolved)
resolve('success');
// 2.reject 函数 pending => rejected
reject('err');
// 3.抛出错误 pending => rejected
throw('抛出错误');
});
改变Promise对象状态和指定回调先后顺序
1.谁先谁后都有可能,正常情况下是先指定回调再改变状态,但也可以先改变状态再指定回调。
如何先改变状态再指定回调
1.在执行器中的是一个同步任务。
2.在执行器中直接调用resolve()和reject()。
3.延迟更长时间才调用then。
得到数据:
1.如果先指定回调,那么当状态发生变化时,回调函数就会调用,得到数据。
2.如果先改变状态,那么当指定回调时,回调函数就会调用,得到数据。
then方法的返回结果
由then方法里面指定回调函数的返回值决定then方法的返回结果。
// then方法的返回结果
let fn = new Promise((resolve,reject)=>{
console.log(resolve,reject);
resolve('success');
});
const result = fn.then((res)=>{
console.log(res);
// // 1.抛出错误,此时then返回一个Promise对象,状态为rejected。
// throw '抛出错误';
// 2.返回结果为一个非Promise对象,此时then返回一个Promise对象,状态为fulfilled(resolved)。
// return 999;
// 3.返回结果为一个Promise对象,此时then返回一个Promise对象,return返回的Promise对象的状态决定then返回Promise对象的状态。
return new Promise((resolve,reject)=>{
console.log(resolve,reject);
resolve('success');
// reject('err');
})
},(err)=>{
console.log(err);
})
console.log(result);
Promise链式调用-串联多个任务
原理就是then方法的返回结果也是一个Promise对象,该Promise对象也有then方法。
// Promise串联多个任务
let fn = new Promise((resolve,reject)=>{
console.log(resolve,reject);
setTimeout(()=>{
resolve('success');
})
});
fn.then((res)=>{
// 这里调用的原因是上面Promise对象resolve('success')返回为成功的。
console.log(res); // success
return new Promise((resolve,reject)=>{
console.log(resolve,reject);
resolve('success-1');
})
}).then((res)=>{
// 这里调用的原因是上面Promise对象 resolve('success-1')返回为成功的。
console.log(res); // success-1
}).then((res)=>{
// 这里返回undefined原因是上层没有返回值,所以为undefined。
console.log(res); // undefined
})
Promise异常穿透
当使用Promise的then链式调用时,可以在最后指定失败的回调。前面任何操作出现了异常,都会传到最后失败的回调中处理。
// Promise串联多个任务
let fn = new Promise((resolve,reject)=>{
console.log(resolve,reject);
setTimeout(()=>{
resolve('success');
})
});
fn.then((res)=>{
console.log(res); // success
return new Promise((resolve,reject)=>{
console.log(resolve,reject);
// resolve('success-1');
reject('err')
})
}).then((res)=>{
console.log(res); // success-1
}).then((res)=>{
console.log(res); // undefined
}).catch((err)=>{
// 前面任何一层出现异常,都会传到该回调函数中处理。
console.log(err);
})
中断Promise链
当使用Promise的then链式调用时,在中间中断,不再调用后面的回调函数。中断方法:在回调函数中返回一个pendding状态的Promise对象。
没中断前:
// Promise串联多个任务
let fn = new Promise((resolve,reject)=>{
console.log(resolve,reject);
setTimeout(()=>{
resolve('success');
})
});
fn.then((res)=>{
console.log(res); // success
}).then((res)=>{
console.log(res); // success-1
}).then((res)=>{
console.log(res); // undefined
}).catch((err)=>{
// 前面任何一层出现异常,都会传到该回调函数中处理。
console.log(err);
})
中断后:
// Promise串联多个任务
let fn = new Promise((resolve,reject)=>{
console.log(resolve,reject);
setTimeout(()=>{
resolve('success');
})
});
fn.then((res)=>{
console.log(res); // success
// 加一个pendding
return new Promise(()=>{})
}).then((res)=>{
console.log(res); // success-1
}).then((res)=>{
console.log(res); // undefined
}).catch((err)=>{
// 前面任何一层出现异常,都会传到该回调函数中处理。
console.log(err);
})
async
使用Promise实现
const fn = ()=>{
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log(resolve,reject);
resolve('fn');
},200)
})
}
const fn1 = ()=>{
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log(resolve,reject);
resolve('fn1');
},1000)
})
}
const fn2 = ()=>{
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log(resolve,reject);
resolve('fn2');
},100)
})
}
fn().then((res)=>{
console.log(res);
});
fn1().then((res)=>{
console.log(res);
});
fn2().then((res)=>{
console.log(res);
});
现在实现的顺序想为:fn->fn1->fn2
const fn = ()=>{
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log(resolve,reject);
resolve('fn');
},200)
})
}
const fn1 = ()=>{
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log(resolve,reject);
resolve('fn1');
},1000)
})
}
const fn2 = ()=>{
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log(resolve,reject);
resolve('fn2');
},100)
})
}
fn().then((res)=>{
console.log(res);
fn1().then((res)=>{
console.log(res);
fn2().then((res)=>{
console.log(res);
})
})
})
这样就会一层一层的调用很多,使用async函数能够解决该问题。
基本介绍在这里:www.runoob.com/w3cnote/es6…
使用async函数可以解决上面问题:
const fn = ()=>{
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log(resolve,reject);
resolve('fn');
},200)
})
}
const fn1 = ()=>{
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log(resolve,reject);
resolve('fn1');
},1000)
})
}
const fn2 = ()=>{
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log(resolve,reject);
resolve('fn2');
},100)
})
}
const fnA = async ()=>{
const fnAwait = await fn(); // 等fn()执行完再往下执行
const fn1Await = await fn1(); // 等fn1()执行完再往下执行
const fn2Await = await fn2(); // 等fn2()执行完再往下执行
console.log(fnAwait);
console.log(fn1Await);
console.log(fn2Await);
}
fnA();
其中,await操作符用于等待一个Promise对象或非Promise对象,它只能在异步函数async function内部使用。
如果它等到的不是一个Promise对象,那await表达式的运算结果就是它等的值。
如果它等到的是一个Promise对象,await就忙起来了,它会阻塞后面的代码,等着Promise 对象resolve,然后将得到resolve的值作为await表达式的运算结果。
然后恢复async函数的执行并返回解析值。