异步任务串联执行解决方案

108 阅读2分钟

概述

实际开发中,有时候会接触到多个异步任务串联执行,就是当前一个异步任务处理完毕,然后再接着调用第二个异步任务接着处理,直到所有异步任务执行完毕,这里总结几种常见的解决方案。

具体方案

首先我们需要准备几个需要异步执行的逻辑代码,异步代码我们通过promise来做

    // 异步任务1:
    function asyncRequestOne() {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve("asyncRequestOne")
            }, 3000)
        })
    }
    // 异步任务2:
    function asyncRequestTwo() {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve("asyncRequestTwo")
            }, 3000)
        })
    }
    // 异步任务3:
    function asyncRequestThree() {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve("asyncRequestThree")
            }, 3000)
        })
    }

方法1:回调函数

这种事最原始的方式,在promise没有之前,解决异步任务的方式主要为这种方式,容易造成回调地狱

//上面示例移除promis
  function getRequest() {
        setTimeout(() => {  //第一层
            console.log('asyncRequestOne');
            setTimeout(() => {  //第二程
                console.log('asyncRequestTwo');
                setTimeout(() => {   //第三层
                    console.log('asyncRequestThree');
                }, 3000)
            }, 1000)
        }, 2000)

    }
    getRequest()

方法1:利用async await

    async function getRequest() {
        let requestDataRequestOne = await asyncRequestOne();
        let requestDataRequestTwo = await asyncRequestTwo();
        let requestDataRequestThree = await asyncRequestThree();
        console.log([requestDataRequestOne, requestDataRequestTwo, requestDataRequestThree]) //['asyncRequestOne','asyncRequestTwo','asyncRequestThree']
    }

    getRequest()

方法2:借助Pormise的链式调用

这种实现方式其实也是axios源码中拦截器的实现方,本质上面还是Promise的链式调用的效果,中间可以加上一些自己错误处理也可以


     function getRequest() {
        let arr = [asyncRequestOne, asyncRequestTwo, asyncRequestThree];
        let p = Promise.resolve();
        while (arr.length) {
            let currentRequest = arr.shift();
            p = p.then(currentRequest);
        }
    }

    getRequest();

方法4:promise.all

Promise.all() 方法接收一个 promise 的 iterable 类型(注:Array,Map,Set 都属于 ES6 的 iterable 类型)的输入,并且只返回一个Promise实例,那个输入的所有 promise 的 resolve 回调的结果是一个数组。

    function getRequest() {
        let p = Promise.all([asyncRequestOne(), asyncRequestTwo(), asyncRequestThree()]).then((res) => {
            console.log(res)//['asyncRequestOne', 'asyncRequestTwo', 'asyncRequestThree']
        })

    }
    getRequest()

总结

本质上,解决异步的执行顺序问题依然是回调函数,只不过promise包装了一层,我们看起来变得更加优雅而已,第二种方法和第三种方法也是本质一样的,await的结果其实就是上次promise成功的值,可以看成第二个方法是第三个方法的语法糖形式。