JavaScript 中存在很多异步操作,Promise 将异步操作队列化,按照期望的顺序执行,返回符合预期的结果。可以通过链式调用多个 Promise 达到我们的目的。
promise 创建时即立即执行即同步任务,即promise里面的会立刻执行,其实resolve也会立即执行,但是它给then才能看出结果,但是then 会放在异步微任务中执行,需要等同步任务执行后才执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| let promise = new Promise((resolve, reject) => { resolve("结果成功了"); console.log('promise执行了') });
let p2 = promise.then(resolve => { console.log(resolve + 'then也执行了'); } );
console.log('123')
|
promise 的 then、catch、finally的方法都是异步任务
如果 resolve 参数是一个 promise ,将会改变promise状态。
下例中 p1 的状态将被改变为 p2 的状态
1 2 3 4 5 6 7 8 9 10
| const p1 = new Promise((resolve, reject) => { resolve( //p2 new Promise((s, e) => { s("成功"); }) ); }).then(msg => { console.log(msg); });
|
当promise做为参数传递时,需要等待promise执行完才可以继承,下面的p2需要等待p1执行完成。
- 因为
p2 的resolve 返回了 p1 的promise,所以此时p2 的then 方法已经是p1 的了
- 正因为以上原因
then 的第一个函数输出了 p1 的 resolve 的参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const p1 = new Promise((resolve, reject) => { setTimeout(() => { resolve("操作成功"); }, 2000); }); const p2 = new Promise((resolve, reject) => { resolve(p1); }).then( msg => { console.log(msg); }, error => { console.log(error); } );
|
then 用于定义当 promise 状态发生改变时的处理,它也类似promise有两种处理方法(两个函数),then实质上也是一个promise,默认返回fulfilled(resolve了)但是也可以返回reject
1
| promise.then(onFulfilled, onRejected)
|
then接收resolve和reject状态括号内信息,并进行操作。
promise 传向then的传递值,如果then没有可处理函数,会一直向后传递
1 2 3 4 5 6 7 8
| let p1 = new Promise((resolve, reject) => { reject("rejected"); }) .then() .then( null, f => console.log(f) );
|
如果 onFulfilled 不是函数且 promise 执行成功, p2 执行成功并返回相同值
1 2 3 4 5 6 7
| let promise = new Promise((resolve, reject) => { resolve("resolve"); }); let p2 = promise.then(); p2.then().then(resolve => { console.log(resolve); });
|
then 是对上个promise 的rejected 的处理,每个 then 会是一个新的promise,默认传递 fulfilled状态
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| new Promise((resolve, reject) => { reject(); }) .then(//这里接收的是reject,但此then执行完了就是fulfilled resolve => console.log("fulfilled"), reject => console.log("rejected") ) .then( resolve => console.log("fulfilled"), reject => console.log("rejected") ) .then( resolve => console.log("fulfilled"), reject => console.log("rejected") ); # 执行结果如下 ejected fulfilled fulfilled
|
如果对象中的 then 不是函数,则将对象做为值传递
1 2 3 4 5 6 7 8 9 10 11
| new Promise((resolve, reject) => { resolve(); }) .then(() => { return { then: "后盾人" }; }) .then(v => { console.log(v); //{then: "后盾人"} });
|
catch
catch用于失败状态的处理函数,等同于 then(null,reject){}
- 建议使用
catch 处理错误
- 将
catch 放在最后面用于统一处理前面发生的错误,它可以收集到很前面的reject
1 2 3 4 5
| const promise = new Promise((resolve, reject) => { reject(new Error("Notice: Promise Exception")); }).catch(msg => { console.error(msg); });
|
catch 也可以捕获对 then 抛出的错误处理
1 2 3 4 5 6 7 8 9
| new Promise((resolve, reject) => { resolve(); }) .then(msg => { throw new Error("这是then 抛出的错误"); }) .catch(() => { console.log("33"); });
|
catch 也可以捕获其他错误,下面在 then 中使用了未定义的变量,将会把错误抛出到 catch
1 2 3 4 5 6 7 8 9 10
| new Promise((resolve, reject) => { resolve("success"); }) .then(msg => { console.log(a); }) .catch(reason => { console.log(reason); });
|
在 promise 中抛出的错误也会被catch 捕获
1 2 3 4 5
| const promise = new Promise((resolve, reject) => { throw new Error("fail"); }).catch(msg => { console.log(msg.toString()+"后盾人"); });
|
finally
无论状态是resolve 或 reject 都会执行此动作,finally 与状态无关。
1 2 3 4 5 6 7 8 9 10 11 12
| const promise = new Promise((resolve, reject) => { reject("hdcms"); }) .then(msg => { console.log("resolve"); }) .catch(msg => { console.log("reject"); }) .finally(() => { console.log("resolve/reject状态都会执行"); });
|
resolve
使用 promise.resolve 方法可以快速的返回一个promise对象
根据值返加 promise
1 2 3
| Promise.resolve("后盾人").then(value => { console.log(value); //后盾人 });
|
reject
和 Promise.resolve 类似,reject 生成一个失败的promise
1
| Promise.reject("fail").catch(error => console.log(error));
|
all
使用Promise.all 方法可以同时执行多个并行异步操作,比如页面加载时同进获取课程列表与推荐课程。
- 任何一个
Promise 执行失败就会调用 catch方法
- 适用于一次发送多个异步操作
- 参数必须是可迭代类型,如Array/Set
- 成功后返回
promise 结果的有序数组
allSettled
allSettled 用于处理多个promise ,只关注执行完成,不关注是否全部执行成功,allSettled 状态只会是fulfilled。即和盘托出之前的办事结果和信息。
下面的p2 返回状态为 rejected ,但promise.allSettled 不关心,它始终将状态设置为 fulfilled 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const p1 = new Promise((resolve, reject) => { resolve("resolved"); }); const p2 = new Promise((resolve, reject) => { reject("rejected"); }); Promise.allSettled([p1, p2]) .then(msg => { console.log(msg); }) // [ // { status: 'fulfilled', value: 'resolved' }, // { status: 'rejected', reason: 'rejected' } // ]
|
race
使用Promise.race() 处理容错异步,和race单词一样哪个Promise快用哪个,哪个先返回用哪个。
- 以最快返回的promise为准
- 如果最快返加的状态为
rejected 那整个promise为rejected执行cache
- 如果参数不是promise,内部将自动转为promise
下面将第一次请求的异步时间调整为两秒,这时第二个先返回就用第二人。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| const hdcms = new Promise((resolve, reject) => { setTimeout(() => { resolve("第一个Promise"); }, 2000); }); const houdunren = new Promise((resolve, reject) => { setTimeout(() => { resolve("第二个异步"); }, 1000); }); Promise.race([hdcms, houdunren]) .then(results => { console.log(results); }) .catch(msg => { console.log(msg); });
|
async/await
使用 async/await 是promise 的语法糖?!,可以让编写 promise 更清晰易懂,也是推荐编写promise 的方式。
async/await 本质还是promise,只是更简洁的语法糖书写
async/await 使用更清晰的promise来替换 promise.then/catch 的方式
async
下面在 hd 函数前加上async,函数将返回promise,我们就可以像使用标准Promise一样使用了。
△加async的函数不会立即执行,它可以返回resolve、reject(),也可以返回一个信息;如果有await在等此函数,那就会执行了——await还有调用它的意思,不只用来接收。
1 2 3 4 5 6 7
| async function hd() { return "houdunren.com";//可以直接返回信息 } console.log(hd()); hd().then(value => { console.log(value); });
|
如果有多个await 需要排队执行完成,我们可以很方便的处理多个异步队列
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| async function hd(message) { return new Promise(resolve => { setTimeout(() => { resolve(message);//也可以返回resolve }, 2000); }); } async function run() { let h1 = await hd("后盾人");//await接收信息 console.log(h1); let h2 = await hd("houdunren.com"); console.log(h2); } run();
|
await
使用 await 关键词后会等待promise 完
await 后面一般是promise,如果不是直接返回
await 必须放在 async 定义的函数中使用
await 用于替代 then 使编码更优雅
下例会在 await 这行暂停执行,直到等待 promise 返回结果后才继执行。
1 2 3 4 5 6 7 8 9 10
| async function hd() { const promise = new Promise((resolve, reject) => { setTimeout(() => { resolve("houdunren.com"); }, 2000); }); let result = await promise; console.log(result); } hd()
|
await调用async:有时需要多个await 同时执行,有以下几种方法处理,下面多个await 将产生等待
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| async function p1() { return new Promise(resolve => { setTimeout(() => { console.log("houdunren"); resolve(); }, 2000); }); } async function p2() { return new Promise(resolve => { setTimeout(() => { console.log("hdcms"); resolve(); }, 2000); }); } async function hd() { await p1(); await p2(); } hd();
|
一般await后面是外部其它的promise对象
1 2 3 4 5 6 7 8 9 10 11 12 13
| async function hd() { return new Promise(resolve => { setTimeout(() => { resolve("fulfilled"); }, 2000); }); } async function run() { let value = await hd(); console.log("houdunren.com"); console.log(value); } run();
|