美文网首页
JavaScript 异步循环 - async/await 的使

JavaScript 异步循环 - async/await 的使

作者: millerLMF | 来源:发表于2019-01-12 14:29 被阅读0次

    如何以顺序或并行方式运行异步循环?

    在对循环进行异步处理之前,我想提醒您如何编写经典的同步循环。

    同步循环

    很久以前我也是这样写For循环:

    for (var i=0; i < array.length; i++) {
      var item = array[i];
      // do something with item
    } 
    

    这样写很好,速度很快,但是有很多可读性和维护问题。我们可以用它更好的版本:

    array.forEach((item) => {
      // do something with item
    });
    

    JS语言在开发中运行很快,我们还有更多的功能和新语法,其中一个是我最常用的 async/await。我现在也经常在用,有时在异步处理数组的里数据时会出现这个问题。

    异步循环

    如何在循环中使用 await ?让我们编写异步函数并 await 每个任务。

    async function processArray(array) {
      array.forEach(item => {
        // define synchronous anonymous function
        // IT WILL THROW ERROR!
        await func(item);
      })
    }
    

    这段代码会出现一个语法错误,因为我们不能在同步函数里使用 await 。“processArray”是一个异步函数,但是我们在这个匿名函数里用到的 forEach 是同步的。

    1.不需要等待结果

    如何修复之前的问题?我们可以这样异步定义匿名函数:

    async function processArray(array) {
      array.forEach(async (item) => {
        await func(item);
      })
      console.log('Done!');
    }
    

    但是 forEach 不会等到所有的步骤都完成,它只会执行任务和执行下一步。作为证明我们可以这样写一个简单例子:

    function delay() {
      return new Promise(resolve => setTimeout(resolve, 300));
    }
    
    async function delayedLog(item) {
      // notice that we can await a function
      // that returns a promise
      await delay();
      console.log(item);
    }
    async function processArray(array) {
      array.forEach(async (item) => {
        await delayedLog(item);
      })
      console.log('Done!');
    }
    
    processArray([1, 2, 3]);
    

    结果输出为:

    Done!
    1
    2
    3
    

    如果不需要等结果这样写是ok的,但是在大多数案例里这不是个很好的逻辑。

    2. 线性处理数组

    要等待结果,我们应该返回到老式的 for 循环,但这一次为了更好的可读性我们可以使用现代写法 for..of。

    sync function processArray(array) {
      for (const item of array) {
        await delayedLog(item);
      }
      console.log('Done!');
    }
    

    结果输出:

    1
    2
    3
    Done!
    

    该代码将依次处理每一项。但是我们可以使用并行运行。

    3.并行处理数组

    我们可以稍微修改下代码然后并行运行:

    async function processArray(array) {
      // map array to promises
      const promises = array.map(delayedLog);
      // wait until all promises are resolved
      await Promise.all(promises);
      console.log('Done!');
    }
    

    这段代码将并行运行许多delayLog 任务。但是对于非常大的数组要小心(并行的任务太多对CPU或内存来说可能比较吃力)。

    也不要混淆“并行”与真正的线程和并行。该代码不能保证真正的并行执行。这取决于您的 item函数(在本演示中是delayedLog)。网络请求、webworker 和其他一些任务可以并行执行。

    感谢阅读!

    出处:Anton Lavrenov Blog

    相关文章

      网友评论

          本文标题:JavaScript 异步循环 - async/await 的使

          本文链接:https://www.haomeiwen.com/subject/fzzqdqtx.html