• JavaScript 循环:如何处理 async/await


    如何串行或者并行运行异步循环?

    在使用循环处理异步的魔法之前,我们先来看下我们是怎么处理同步循环的。

    同步循环

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

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

    后来 JavaScript 提供了很多新的特性,现在我们会更倾向于用下面这种写法:

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

    在开发过程可能会有这么一种需求,我们需要在循环中异步处理 item,那么可以怎么做呢?

    异步循环

    如何在循环中使用 await?我们试着写一个异步函数,然后 await 每一次循环任务。

    async function processArray(array) {
      array.forEach(() => {
        //  define synchronous anonymous function
        //  it will throw error here
        await func(item)
      });
    }

    这个代码会抛出一个错误,因为我们不能在同步方法中使用 await, processArray 确实是异步函数,但是 array.forEach 里的匿名函数是同步的。

    1. 不要等待结果

    要处理这个问题,我们可以把这个匿名函数定义为异步的:

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

    但是这样的话 forEach 方法就相当于异步的了,不会等待遍历完所有的 item,例如下面这段代码:

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

    将会输出:

    Done!
    1
    2
    3

    如果你不需要等待这个循环完成,这样就已经可以了。但是大部分情况我们还是需要等待这个循环完成才进行之后的操作。

    2. 串行遍历

    要等待所有的结果返回,我们还是要回到老式的 for 循环写法:

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

    最后的结果符合我们的预期:

    1
    2
    3
    Done!

    上面这段的遍历代码是串行执行的,我们也可以把它换成并行的。

    3. 并行遍历

    我们可以稍微更改上面的代码来编程并行的:

    async function processArray(array) {
      //  map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。
      //  async 修饰的方法返回值是一个promise对象,因此下面map的返回值就是一个promise列表
      const promiseArr = array.map(delayedLog);
      //  wait until all promises are resolved
      await Promise.all(promiseArr);
      console.log('Done!');
    }

    (注意:对于特别大的数组不建议使用这种写法,太多的并行任务会加重 CPU 和内存的负荷)

     转自:https://zhuanlan.zhihu.com/p/31000936

  • 相关阅读:
    SQLSERVER中的sp_reset_connection存储过程的作用
    SQLSERVER数据库经常置疑的原因
    sqlserver2005数据库邮件
    SQLSERVER书签查找的通俗理解
    msdb数据库里的表究竟存储什么信息
    造成阻塞和死锁的3大原因:
    SQLSERVER中的锁资源类型RID KEY PAG EXT TAB DB FIL
    总结一下要影响SQLSERVER锁的申请和释放行为要考虑的因素
    Linux下getsockopt/setsockopt 函数说明
    HTTP协议详解(转)
  • 原文地址:https://www.cnblogs.com/duhuo/p/6129025.html
Copyright © 2020-2023  润新知