同步、异步任务串行

111 阅读1分钟

基于一次阿里笔试,递归实现异步同步串行

异步或者同步任务,这不重要

let arr = [
  (res) =>
    new Promise((resolve) =>
      setTimeout(() => {
        console.log('task: task2 complete');
        resolve({ success: true, data: `${res} + data1` });
      }, 1000)
    ),
  (res) => {
    console.log('task: task1 complete');
    return { success: true, data: `${res} + sync function result` };
  },
  (res) =>
    new Promise((resolve) =>
      setTimeout(() => {
        console.log('task: task3 complete');
        resolve({ success: true, data: `${res} + data2` });
      }, 1000)
    ),
  (res) => {
    console.log('task: task4 complete');
  }
];

主函数:

function createFlow(arr, callback, originData = 'origin data') {
  return new Promise((resolve) => {
    let result = originData; //存放每一次的结果,实现链式传递
    _createFlow(arr, callback);

    function _createFlow(arr, callback) {
      const _arr = arr.slice(); //不影响输入参数
      while (_arr.length) {
        const task = _arr.shift();

        if (typeof task === 'function') {
          let value = task(result); //执行函数
          if (!(value instanceof Promise)) {
            if (value == undefined) continue;
            result = value.data;
            console.log(`step: ${result}` + '\n');
            continue; //普通的函数就不在需要then操作了,进入下一循环
          }

          if (value instanceof Promise) { // return value is Promise
            value.then((res) => {
              const { success, data } = res;
              if (success) result = data; //return value 传递给闭包变量result
              console.log(`step: ${result}` + '\n');
              _createFlow(_arr, callback); //继续递归调用
            });
            return; //一定要return这步是重点,如果不return的话,还会走while循环,异步任务将会并发执行
          }
        }
      } //while 循环执行完,即所有的task都执行完毕了,最后要将result resolve出去

      resolve(result); //在返回的promise , get The final return value
      // callback && callback(result); //如此也可以在第二个回调函数中拿到最后返回的value
    }
  });
}

测试代码

async function run() {
  const res = await createFlow(arr);//也可以穿入第二次回调函数,可以做一些所有task任务都完成之后的工作等等。
  console.log(res);
}
run();

结果截图:

image.png