异步串行

177 阅读1分钟

基于一次阿里的笔试题

给出任务队列

let res = [
    //同步任务1
  (res) => {
    console.log('task1 complete');
    return { success: true, data: res + ' ' + 'res' };
  },
   //异步任务1
  (res) =>
    new Promise((resolve) =>
      setTimeout(() => {
        console.log('task2 complete');
        resolve({ success: true, data: res + ' ' + 'data1' });
      }, 1000)
    ),
   //异步任务2
  (res) =>
    new Promise((resolve) =>
      setTimeout(() => {
        console.log('task3 complete');
        resolve({ success: true, data: res + ' ' + 'data2' });
      }, 1000)
    )
];

给出同步任务和异步任务,结果依赖上一次的任务结果,类似回调地狱

1. 基本乞丐版async await实现方案

async function createFlow(arr) {
  return new Promise(async (resolve, reject) => {
    let result = null;
    for (let task of arr) {
      let { success, data } = await task(result);
      result = data;
    }
    resolve(result);
  });
}
createFlow(res).then(console.log);

这种方法没啥说的,就是await阻塞代码

2. 进阶乞丐版reduce实现方案

function createFlow(arr, originData) {
   //先来一步判断,是否为数组,不是直接throw出去
  if (!Array.isArray(arr))
    throw new Error('The first argument must be an Array!');

  return new Promise((resolve) => {
    const [firstFn, ...other] = arr;
    other.reduce((preValue, currentFn, index) => {
        
      //不是promise异步任务,直接此逻辑
      if (!(preValue instanceof Promise)) {
      //if判断success,如果有err展示降级UI(具体逻辑没有写)
        const { success, data } = preValue; 
        return currentFn(data);
      }
      
      preValue.then((res) => {
        const { success, data } = res;
        const promise = currentFn(data);
        
        //⚠️⚠️⚠️为了让外部拿到最终的result,在这里判断是否最后一个task,并且resolve出去
        if (index === other.length - 1) resolve(promise); 
       
        return promise;
      });
    }, firstFn(originData));//更改首项默认值
  });
}

createFlow(res, 'origin data').then(console.log);

在校学生,水平有限,不喜勿喷