【问题标题】:Create asynchronous waterfall from objects从对象创建异步瀑布
【发布时间】:2018-03-16 21:38:41
【问题描述】:

假设我有一个具有异步方法的对象数组:

[
  {
    partOne: function(input) {
      // Do something async
    },
    partTwo: function(result) {
      // Do something w/ result of partOne
    }
  },
  {
    partOne: function(resultOfPrevious) {
      // Do something async
    },
    partTwo: function(result) {
      // Do something w/ result of partOne
    }
  },
  {
    partOne: function(resultOfPrevious) {
      // Do something async
    },
    partTwo: function(result) {
      // Do something w/ result of partOne
    }
  }
]

我想用我的输入执行第一个对象的 partOne,将结果(异步)传递给 partTwo 回调,然后将 partTwo 的结果作为输入传递给下一个对象的 partOne,依此类推。该数组可以是一个或多个对象。我想知道执行这种代码的最佳模式是什么?

它有点类似于 async.js 的瀑布方法:https://caolan.github.io/async/docs.html#waterfall,但我想知道如何在没有库且可能使用更简洁的代码的情况下做到这一点?

不确定 async/await 是否有帮助?

【问题讨论】:

    标签: javascript node.js asynchronous async-await async.js


    【解决方案1】:

    假设您在原始问题中给出的对象数组位于名为瀑布的变量下

    let collector = [];
    for (waterfallObj of waterfall) {
      let tempArr = Object.values(waterfallObj);//get the functions out of the object
      for (waterfallFunc of tempArr) {
        collector.push(waterfallFunc);
      }
    }
    //now you have your functions in order in collector
    function recursiveCallback(i) {
      if (i>collector.length-1) {
        return;//if there are no more to call then return
      }
    
      collector[i]().then(function(){
        recursiveCallback(i+1);
      });
    }
    

    如果你想让下一个函数对前面的函数值做一些事情,那么只需将 then 更改为 then(function(passedValue ,然后在其中的 recursiveCallback 调用中使用该传递值

    【讨论】:

    • 你不是popping 从collector 的任何地方,所以recursiveCallback 函数只会抛出maximum call stack size exceeded
    • 为什么我需要弹出?当所有收集器功能都已处理完毕时,我有一个返回语句
    • 我的错,你是完全正确的。我忽略了i>... 部分。
    【解决方案2】:

    另一个不收集每个回调到数组的选项,使用async/await

    async function processWaterfallObject (data, input) {
      let result = input
    
      for (let entry of data) {
         result = await entry.partOne(result)
         result = await entry.partTwo(result)
      }
    
      return result
    }
    

    这假定您的 data 数组中的函数要么是 async,要么返回 Promise


    async/await 目前由every major browser 支持,并且自7.6.0 起在node 中可用。

    【讨论】:

    • 很好,很干净。
    【解决方案3】:

    这是一个调用堆栈中每个异步函数的简单函数

    function drain(stack, initialArg) {
      stack.reduce(function (sectArg, section) {
        return Object.keys(section).reduce(async function (arg, key) { 
          return await section[key].call(null,arg)
        }, sectArg) 
      }, initialArg)
    }
    

    要使用它,请确保堆栈中的每个函数都返回一个值

    var stack = [
      {
        partOne: function(input) {
          // Do something async
          console.log('section one  partOne', input)
          return 'section one partOne output'
        },
        partTwo: function(result) {
          // Do something w/ result of partOne
          console.log('section one  partTwo', result)
          return 'section one partTwo output'
        }
      },
      {
        partOne: function(resultOfPrevious) {
          // Do something async
          console.log('section two  partOne', resultOfPrevious)
          return 'section two partOne output'
        },
        partTwo: function(result) {
          // Do something w/ result of partOne
          console.log('section two  partTwo', result)
          return 'section two  partTwo output'
        }
      },
      {
        partOne: function(resultOfPrevious) {
          // Do something async
          console.log('section three  partOne', resultOfPrevious)
          return 'section three partOne output'
        },
        partTwo: function(result) {
          // Do something w/ result of partOne
          console.log('section three  partTwo', result)
          return 'section three partTwo output'
        }
      }
    ]
    

    这样你就可以像调用堆栈一样

    drain(stack, 'initialArg')
    

    查看这个 jsfiddle:https://jsfiddle.net/kqj0rror/

    【讨论】:

    • 这不考虑异步函数。
    • 太棒了!我还注意到你是calling section[key]this - 我不确定这是否是个好主意,它可能会导致代码中出现很多意想不到的错误。也许您应该改用null
    • 我同意null 更合适。我会更新的。谢谢你的提示。
    猜你喜欢
    • 2018-11-13
    • 2020-09-06
    • 2015-07-18
    • 2015-04-28
    • 1970-01-01
    • 2019-01-02
    • 1970-01-01
    • 2020-10-13
    • 2014-10-09
    相关资源
    最近更新 更多