美文网首页
neo-async each

neo-async each

作者: AizawaSayo | 来源:发表于2021-06-01 03:51 被阅读0次

    GitHub地址

    Neo-Async 是一个为异步 JavaScript (也有同步) 提供一些方法的库。它被认为是 Async 的替代品,几乎完全覆盖了Async的功能,而且运行速度更快。

    Neo-Async 库提供的所有方法,如map、parallel、series、waterfall...诸如此类,都遵循Node.js约定,拥有一个以 Error 为第一个参数的回调方法。这个回调会作为最后一个参数传给该方法的异步函数参数,并且只能被调用一次。文字阐述有点绕,我们以 neo-async 的 each 为例,用 code 来说明:

    我们参考下 async.each() 的文档,neo-async.each 相当于它的升级版,不仅同样能完成集合 (几乎任何类型) 的异步迭代,还可以直接给 iterator (迭代器参数) 传数组的 index 或对象的 key (可选),而 async 要借助 eachOf 才能实现。

    语法each(coll, iteratee, callback)
    将 iteratee 函数并行 (不能保证按顺序) 地应用于 coll 中的每一项 (item)。iteratee 除了 item 还可以接收一个回调(即 each 的第三个参数 -- callback 方法) 作为参数。如果 iteratee 传递一个值给这个回调 (通常是错误),则会立即调用这个 each 的 callback。不传递参数 callback 则会在所有 item 被 iteratee 处理完后执行。

    参数:

    coll:<Array | Iterable | AsyncIterable | Object>
    一个需要迭代的集合

    iteratee:<AsyncFunction> :function(item, [index|key], callback)
    一个应用于集合(coll)每一项(item)的异步函数,默认接收item, callback两个参数。若需要在iteratee中接收 Array 的 index 或 Object 的 key,传给第二个可选参数即可。
    iteratee内手动调用callback([sth])即可执行 each 第三个参数方法 (主callback)。

    callback :<Function> :function(err)
    当所有 iteratee 处理完成或发生错误时调用的回调。接收一个 (err) 参数。

    在 iteratee 内调用 callback(err)
    const async = require('neo-async')
    var array = [1, 2, 3]
    
    // 假设这是一个异步方法,用 setTimeout 模拟
    var someAsyncFun = (data, cb) =>
      setTimeout(() => {
        if (data > 2) return cb('err: 数字不能大于2')
        const newData = data * 2
        cb(null, newData)
      }, Math.random() * 1000)
    
    // 应用于每一项的迭代器函数
    var iterator = function (item, callback) {
      someAsyncFun(item, (err, result) => {
        console.log(result) // 拿到异步返回结果
        callback(err, result) // 把`err`传递给回调并执行
      })
    }
    
    async.each(array, iterator, (err, res) => {
      console.log('回调执行:', err, res)
    })
    

    这时,我们发现当 callback 被调用时传递了参数,each 的第三个参数(即主 callback)就会立即执行,并且拿到的 err 就是我们传递的值。文档中 callback 只接收一个参数,实测传了第二个参数在执行的时候永远是 undefined。

    当传递了错误,主 callback 立即执行 第三个参数 callback 执行的时间取决于何时callback带参
    在 iteratee 内调用 callback()

    这次我们写个简化版。
    callback 不放在 iteratee 异步方法内最后调用可能会出现不可预期的结果,且本意是等项目的迭代函数全部执行完再调用 (不报错的情况),因此我们应该保证将其写在其他语句之后。neo-async.each 例子中 iteratee 的 callback 参数都用 done 来代替以表明语义。

    // 相同部分省略
    async.each(
      array,
      (item, callback) => {
        setTimeout(() => {
          const newData = item * 2
          console.log(newData)
          // if (err) return callback(err) // 如果多次回调,的推荐写法
          // 举例:if (item === 2) return callback('err: 数字不能等于2')
          callback()
        }, Math.random() * 1000)
      
      },
      err => {
        console.log('回调执行:', err)
      }
    )
    

    callback() 也能实现手动执行回调,执行时机是所有项目被 iteratee 迭代处理完成之后。

    image.png

    注意⚠️:因为回调在 iteratee 内只能被调用一次,如果出于条件判断等因素需要多次 callback() ,则在前面加上 return 比较稳妥,如:

    var iterator = function(item, callback) {
      someAsyncFun(item, (err, result) => {
        if (err) return callback(err)
        callback(null, result)
      });
    };
    

    当然如果是上面的 each 方法传了这个 iterator 函数,callback 只接收一个 err 参数。

    相关文章

      网友评论

          本文标题:neo-async each

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