Javascript 从对象创建异步瀑布

Javascript 从对象创建异步瀑布,javascript,node.js,asynchronous,async-await,async.js,Javascript,Node.js,Asynchronous,Async Await,Async.js,假设我有一个具有异步方法的对象数组: [ { partOne: function(input) { // Do something async }, partTwo: function(result) { // Do something w/ result of partOne } }, { partOne: function(resultOfPrevious) { // Do something async

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

[
  {
    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:的瀑布方法,但我想知道,如果没有库,可能还有更干净的代码,我怎么能做到这一点


不确定async/await是否有帮助

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

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(函数)(passedValue,然后在其中的递归回调调用中使用该passedValue,假设原始问题中给出的对象数组位于名为瀑布的变量下

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(函数)(passedValue,然后在其中的递归回调调用中使用该passedValue)

另一个选项,而无需使用
async/wait
收集对数组的每个回调:

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
}
这假设
数据
数组中的函数是
异步
或返回
承诺



async/await
当前受
节点的支持,并且在
节点中可用,因为
7.6.0

使用
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
}
这假设
数据
数组中的函数是
异步
或返回
承诺



async/await
目前受
节点的支持,并且在
节点中可用,因为
7.6.0

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

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

请参阅此JSFIDLE:

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

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

查看此JSFIDLE:

您没有
pop
ping
收集器
的任何位置,因此
递归回调
函数将抛出,超过
最大调用堆栈大小
。为什么我需要弹出?我在其中有一个返回语句,用于在所有收集器函数都处理得很糟糕的情况下,您将理顺了。我忽略了
I>…
部分。您没有
pop
ping
收集器的任何位置,因此
recursiveCallback
函数将在超出
最大调用堆栈大小的情况下抛出。为什么我需要弹出呢?我在那里有一个return语句,用于所有收集器函数都已打开时处理得很糟糕,你完全正确。我忽略了
I>部分。这并不能解释函数是异步的。太好了!我还注意到你在
调用
部分[key]
使用
-我不确定这是否是一个好主意,它可能会导致代码中出现许多意想不到的错误。也许你应该使用
null
来代替?我同意
null
更合适。我会进行更新。谢谢你的提示。这并不能说明函数是异步的。太好了!我也注意到了d您正在
呼叫
ing
部分[键]
使用
这个
-我不确定这是不是一个好主意,它可能会导致代码中出现很多意想不到的错误。也许你应该使用
null
来代替?我同意
null
更合适。我会进行更新。谢谢你的提示。非常好,非常干净。非常好,非常干净。