async/await|async/await 和 promise/promise.all 的示例

概述 promise 为 js 提供了并发异步能力。
promise.all 可以等待一批 promise 任务 全部执行完成 后返回 结果集合
【async/await|async/await 和 promise/promise.all 的示例】async/await 可以使一批 promise同步串行 的模式去执行(一些接口依赖场景是有此需求的)。
Promise / Promise.all Promise 提供了异步接口,搭配 resolve/reject 可以很方便的让业务代码并发执行,但同时也产生了 回调地狱 问题。
Promise.all 则是并发执行任务集合,且等待所有的任务执行完成后,一并返回结果集。

function promiseReq(url) { return new Promise((resolve, reject) => { fetch(url).then((res) => { resolve(res) }).catch((e) => { reject(e) }) }) } promiseReq(url) .then(res => console.log(res)) .catch(e => console.error(e))

async / await async 正如其名,用于定义一个异步方法,它会自动将方法封装成一个 Promise 返回,并且使用 return 代表 resolvethrow 代表 reject
async function asyncFoo() { if (Math.floor(Math.random() * 10) > 5) { return "asyncFoo resolved" } throw "asyncFoo rejected" }console.log(asyncFoo() instanceof Promise)asyncFoo().then((res) => { console.log(res) }).catch((e) => { console.error(e) })

但日常开发中我们并不会单独使用 async,而是搭配 await 去同步多个 promise 任务。await 的作用就是让 Promise 的异步回调降维至同步模式。
场景1 - 接口并发执行且数据结果汇总 当需要等待一批接口的数据全部返回后,才可以继续执行后面的接口时,则可以使用 Promise.all 来处理 一批任务。其会 并发 执行 任务集合 中的 Promise 任务,等待所有的任务执行完成后,汇总结果并返回(结果数组)。
function promiseEnum(countDown) { return new Promise((resolve, reject) => { setTimeout(() => { resolve("promiseEnum countDown " + countDown) }, countDown * 1000) }) }Promise.all([promiseEnum(1), promiseEnum(2), promiseEnum(3)]) .then((values) => { // 等待 1 2 3 并发执行完成 console.log("Promise.all values", values) promiseEnum(4).then((res4) => { console.log(res4) }) })

场景2 - 接口顺序依赖执行 试想一下,有4个数据接口,后者依赖前者返回的结果才能继续执行,如果使用传统的 Promise,那大概就是
// callback hell promiseReq(url1).then((res1) => { promiseReq(url2 + res1).then((res2) => { promiseReq(url3 + res2).then((res3) => { promiseReq(url4 + res3).then((res4) => { console.log("promiseReq finished") }).catch(err => console.error(err)) }).catch(err => console.error(err)) }).catch(err => console.error(err)) }).catch(err => console.error(err))

使用 async/await 则可以友好的解决依赖回调问题,让代码以 同步 的风格编写和执行。
// 使用 async/await 则可以友好的解决依赖回调问题 async function promiseSyncReq() { let res1 = await promiseReq(url1) let res2 = await promiseReq(url2 + res1) let res3 = await promiseReq(url3 + res2) let res4 = await promiseReq(url4 + res3) return res4 } promiseSyncReq().then((res4) => { console.log(res4) }).catch(e => console.log(err))

async/await 的执行耗时等于各个 Prmoise 累计的总耗时(执行流本就是要串行,耗时自然是各接口的累计,回调模式也一样的)。
async function awaitAllPromise() { let res1 = await promiseEnum(1)//阻塞等待 耗时1秒 let res2 = await promiseEnum(2)//阻塞等待 耗时2秒 let res3 = await promiseEnum(3)//阻塞等待 耗时3秒 let res4 = await promiseEnum(4)//阻塞等待 耗时4秒//执行总耗时为各 Promise 耗时的累加 return [res1, res2, res3, res4] }

组合使用 async/awaitpromise/promise.all 组合使用,灵活实现 部分任务并发执行部分任务同步执行
async function batchExec() { console.group("batchExec")let startTime = new Date().getTime() console.log("batchExec start", startTime)// 等待 1,2,3 并发执行完成 let paralValues = await Promise.all([promiseEnum(1), promiseEnum(2), promiseEnum(3)])let paralTime = new Date().getTime() console.log("parallel 1,2,3 finished", paralTime, (paralTime - startTime) / 1000, paralValues)// 再继续执行 4 let res4 = await promiseEnum(4)let endTime = new Date().getTime() console.log("batchExec end", endTime, (endTime - startTime) / 1000)console.groupEnd("batchExec")return [...paralValues, res4] }batchExec() .then(res => console.log(res)) .catch(e => console.error(e))

    推荐阅读