【问题标题】:How to execute asynchronous tasks in order如何按顺序执行异步任务
【发布时间】:2021-07-26 22:12:14
【问题描述】:

我目前正在用 Javascript 中的异步函数进行试验,我偶然发现了一个案例,我想按照它们在数组中的放置顺序执行一组异步函数。

我还希望是否可以将参数传递给异步函数。使用我现在的solution,两个带参数的函数先同时执行,然后其他两个函数一个接一个地执行。

const asyncOne = async (value = "no value passed to async 1") => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log(value);
      resolve();
    }, 1000);
  });
};

const asyncTwo = async (value = "no value passed to async 2") => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log(value);
      resolve();
    }, 1000);
  });
};

const sequence = async tasks => {
  const resolve = Promise.resolve(null);

  await tasks.reduce(
    (promise, task) =>
      promise.then(() => (typeof task === "function" ? task() : task)),
    resolve
  );
};

(async () => {
  const res = await sequence([asyncOne("first"), asyncTwo, asyncOne, asyncTwo("last")]);
})();

预期输出:

"first"
"no value passed to async 2"
"no value passed to async 1"
"last"

实际输出:

"first"
"last"
"no value passed to async 2"
"no value passed to async 1"

【问题讨论】:

  • 首先,您不应该将asyncnew Promise 混合和匹配。

标签: javascript asynchronous promise sequence


【解决方案1】:

正如我在评论中提到的,您不应该将 new Promiseasync 混为一谈——没有必要,您只会让自己和任何未来的读者感到困惑。

无论哪种方式,async 函数将开始同步执行,这就是您看到序列的原因(firstlast 超时同时开始)。要解决这个问题,您需要使用一个函数来调用返回承诺的函数,如下所示:

function delay(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

async function asyncOne(value = "async1 default") {
  await delay(1000);
  console.log(value);
}

async function asyncTwo(value = "async2 default") {
  await delay(1000);
  console.log(value);
}

async function sequence(tasks, init = undefined) {
  let value = init;
  for (let task of tasks) {
    if (typeof task === "function") value = await task(value);
    else value = await task;
  }
  return value;
}

(async () => {
  await sequence([
    () => asyncOne("first"),
    asyncTwo,
    asyncOne,
    asyncTwo.bind(this, "last"), // can also use `bind` instead of an anonymous arrow function
  ]);
})();

此实现还允许您将值从一个promise 链接到另一个promise,并允许将初始值传递给第一个promise-returning 函数,á la

await sequence([asyncTwo], "hello!");

【讨论】:

    【解决方案2】:

    asyncOne("first")asyncTwo("last") 调用函数并立即执行它们,因此它会阻止您按顺序执行它们。

    改为asyncOne.bind(this, "first"),它不会立即执行该函数,允许您稍后执行。

    (async () => {
    
        const functions = [
            asyncOne.bind(this,"first"),
            asyncTwo,
            asyncOne,
            asyncTwo.bind(this, "last")
        ];
    
        for(let f of functions){
            await f()
        }
    
    })();
    

    【讨论】:

    • for..in 用于迭代对象。 for..of 用于遍历数组或其他有序集合。
    • 确实,错字。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-19
    • 2017-08-30
    • 2022-08-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多