2

Overview

  1. promise concurrent asynchronous capability for js, and there is a problem of callback hell.
  2. async/await can make a batch of promise in synchronous and sequential mode (some interface-dependent scenarios have this requirement), and solve the problem of callback hell.
  3. promise.all may wait a number promise task all returned after the completion of execution, together with return result set, for subtasks not interdependent, but subsequent tasks need to rely data before the results of a plurality of subtasks scene.

Promise / Promise.all

Promise provides an asynchronous interface. With resolve/reject it is very convenient for business code to be executed concurrently.

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

console.log("promise1 promise2 execute")

Promise.all is a set of concurrent execution tasks, and after all tasks are completed, the result set is returned.

async / await

async as its name suggests, is used to define an asynchronous method. It will automatically encapsulate the method into a Promise return, and use return represent resolve , and throw represent 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)
})

But in daily development, we will not use async alone, but use await to synchronize multiple promise tasks. await role is to make Promise asynchronous dimensional cut back to synchronous mode.

Scenario 1-Concurrent execution of interfaces and summary of data results

When you need to wait for a batch of interface data to return before you can continue to execute the following interface, you can use Promise.all to process a batch of tasks. It will concurrent execution tasks set Promise task, wait for all task execution is completed, the summary results and return (resulting array).

For example, refresh the user information interface, 1. Request basic data 2. Request order data 3. Request invitation data 4. Refresh is complete, 4 can only be executed after all 1, 2, and 3 are executed, which is very suitable for the scene of Promise.all([1,2,3]).then((res) => {4}) .

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)
    })
})

Scenario 2-Interface order depends on execution

Imagine that there are 4 data interfaces. The latter depends on the results returned by the former to continue execution. If you use the traditional Promise , it is probably

// 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))

Using async/await can solve the dependency callback problem friendly, allowing the code to be written and executed in the synchronous

// 使用 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 is equal to the respective time-consuming Prmoise accumulated total time (this is to perform a serial stream, time-consuming nature of the interfaces is accumulated, the callback mode is also the same).

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]
}

Use in combination

async/await and promise/promise.all used in combination to achieve flexible part of the task concurrent execution, part of the task synchronously.

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

big_cat
1.7k 声望130 粉丝

规范至上