串行执行异步、同步任务小记

184 阅读1分钟

场景

​ 有一系列的任务函数,task1,task2....taskN,任务执行执行可异步或同步方式,实现一个run函数按照顺序依次串行执行任务;run(task1,task2....taskN)

Promise实现

​ 调用Promise.resolve()生成resolved状态的 Promise 对象p,循环更新p,将要执行的函数task通过p.then方法进行串联,并且将执行结果push到结果数组,最后将更新的data返回,这样保证后面可以调用then方法

function runPromise(...tasks) {
    const res = [];
    let p = Promise.resolve();
    for (let task of tasks) {
      // 核心 拼接链式执行
      p = p.then(con => {
        res.push(con);
        return task();
      });
    }
    return p.then(con => {
      res.shift();
      res.push(con);
      return res;
    }).catch(e => {
      return e;
    });
}

Generator 实现

需要自己写遍历器,遍历执行

function runGenerator(...tasks) {
    const res = [];
    return spawn(function* () {
      for (let task of tasks) {
        const con = yield task();
        res.push(con);
      }
      return res;
    });
 }

// 遍历器 
function spawn(generatorFn) {
    return new Promise((resolve, reject) => {
      const gen = generatorFn(); // 遍历器对象
      function step(nextFn) {
        let next;
        try {
          next = nextFn();
        } catch (error) {
          return reject(error)
        }
        if (next.done) { // 结束直接返回
          return resolve(next.value);
        }
        Promise.resolve(next.value).then(function (value) {
          // gen.next(value) 传的参数将作为上一个yiled表达式的返回值
          step(function () { return gen.next(value); });
        }, function (err) { // 异常
          step(function () { return gen.throw(err); })
        });
      }
      // 启动遍历器
      step(function () { return gen.next(); });
    });
}

async 实现

async function runAsync(...tasks) {
    const res = [];
    try {
      // 遍历任务 依次执行
      for (let task of tasks) {
        const con = await task();
        res.push(con);
      }
    } catch (error) {
      return error;
    }
    return res;
}

测试

function task1() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(1);
    }, 200);
  });
}

function task2() {
  return 2;
}

function task3() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(3);
    }, 100);
  });
}

// 输出结果 [1,2,3];
runPromise(task1, task2, task3).then(res => {
  console.log(res);
});

// runGenerator(task1, task2, task3).then(res => {
//   console.log(res);
// });

// runAsync(task1, task2, task3).then(res => {
//   console.log(res);
// });