Skip to content

函数顺序调用

需求场景

  • 需要按照顺序调用多个函数,并且每个函数都需要等待前一个函数执行完成后再执行
  • 如果前一个函数执行成功(返回 true),继续执行下一个函数,否则(返回 false),后续函数不再执行
  • 并且同时支持同步和异步函数

实现方式

  • 使用 for 循环,依次执行每个函数,使用 await 继发执行 (Unexpected await inside a loop.eslintno-await-in-loop )
ts
// for循环中 await 继发执行
async function callMethodsSequentially(methods: (() => boolean | Promise<boolean>)[]) {
  for (const method of methods) {
    const result = await Promise.resolve(method()); // 确保同步和异步方法都能被正确处理
    if (result === false) {
      return false;
    }
  }
  return true;
}
  • 使用 Promise.all 并发执行多个函数(无法控制每个函数的执行顺序)
ts
async function callMethodsSequentiallyPromiseAll(methods: (() => boolean | Promise<boolean>)[]) {
  const results = await Promise.all(methods.map(method =>
    Promise.resolve(method())
  ));

  for (const result of results) {
    if (result === false) {
      return false;
    }
  }

  return true;
}
  • 使用 reduce 处理 继发处理
ts
async function callMethodsSequentiallReduce(methods: (() => boolean | Promise<boolean>)[]) {
  let finalResult = true

  await methods.reduce(async (promise, method) => {
    await promise
    if (!finalResult) {
      return
    }
    const result = await method()

    if (result === false) {
      finalResult = false
    }
  }, Promise.resolve())

  return finalResult
}
  • 使用生成器, yield 继发处理,while循环 (Unexpected await inside a loop.eslintno-await-in-loop)
ts
// 生成器处理 yield 继发处理 while循环
async function callMethodsSequentiallyGeneratorYieldWhile(methods: (() => boolean | Promise<boolean>)[]) {
  function* methodGenerator() {
    for (const method of methods) {
      const result = yield method();
      if (result === false) {
        return false;
      }
    }
    return true;
  }

  const generator = methodGenerator();
  let result = generator.next();

  while (!result.done) {
    const promise = Promise.resolve(result.value);
    const resolvedResult = await promise;
    result = generator.next(resolvedResult);
  }

  return result.value;
}
  • 使用生成器, yield 继发处理,递归函数
ts
// 生成器处理 yield 继发处理 递归函数
export async function callMethodsSequentiallyGeneratorYieldRecursive(methods: (() => boolean | Promise<boolean>)[]) {
  function* methodGenerator(): Generator<boolean | Promise<boolean>, boolean, boolean> {
    for (const method of methods) {
      const result: boolean | Promise<boolean> = yield method();
      if (result === false) {
        return false;
      }
    }
    return true;
  }

  const generator = methodGenerator();
  let result = generator.next();

  async function processNext(): Promise<boolean> {
    if (result.done) {
      return result.value;
    }

    const promise = Promise.resolve(result.value);
    const resolvedResult: boolean = await promise;
    result = generator.next(resolvedResult);
    return processNext();
  }

  return processNext();
}