从对象创建异步瀑布

Create asynchronous waterfall from objects

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

[
  {
    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 是否有帮助?

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

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 调用中使用该 passedValue

另一个不收集每个回调到数组的选项,使用 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 或 return a Promise.


async/await 当前受 every major browser 支持,自 7.6.0.

起可用于 node

下面是调用堆栈中每个异步函数的简单函数

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)
}

要使用它,请确保您中的每个函数都堆叠 returns 一个值

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/