概述

promise 为 js 提供了并发异步能力。

promise.all 能够期待一批 promise 工作 全副执行实现 后返回 后果汇合

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 hellpromiseReq(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))