JavaScript承诺:使用广度优先遍历递归构建承诺链

时间:2016-03-09 00:48:31

标签: javascript promise es6-promise

原生Javascript ES5 / ES6承诺

我试图导入具有递归关系的数据 数据库(mongodb)正在分配id - 必须加载父(异步) 在它之前可以加载孩子(也是异步)。

例如,此任务列表中的任务B.

任务A - 某些过程

任务B - 递归异步加载(先行遍历)

任务C - 取决于任务B

注意,因为任务C无法启动,直到任务B完成,我假设 需要建立一个在完成之前不会退出的承诺链。

假设正在构建的链看起来像这样: (树只有1头)

promiseParent.then(Promise.all(childrenPromises.then(Promise.all(grandChildrenPromsies.then(....)))))

我想它会像广度优先队列那样遍历(我更愿意 如果可能的话,尽量避免使用队列数据结构

我发现这个很难破解。任何建议或 溶液

1 个答案:

答案 0 :(得分:2)

可以动态扩展Promise链,只需在任何.then履行处理程序中返回一个承诺,就可以在链中的任意位置插入新链接。

假设每个任务都使用其子数组进行解析。如果孩子可以并行处理,那么:

promiseParent
.then(children => Promise.all(children.map(child => loadChild(child))))
.then(grandchildren => Promise.all(grandchildren.map(child => loadChild(child))))

应该这样做。如果必须按顺序处理儿童,则:

let sequence = (a, f) => a.reduce((p, c) => p.then(() => f(c)), Promise.resolve());

promiseParent
.then(kids => sequence(kids, kid => loadChild(kid)).then(() => nextGen())
.then(gkds => sequence(gkds, kid => loadChild(kid)).then(() => nextGen())

会这样做(我通过假设nextGen知道返回下一代来简化。)

如果必须递归发现孩子的数量,那么:

let loadChildrenRecursively = child => loadChild(child)
  .then(nextChild => nextChild && loadChildrenRecursively(nextChild));

promiseParent
.then(firstChild => loadChildrenRecursively(firstChild)).then(() => nextGen())
.then(firstGchild => loadChildrenRecursively(firstGchild)).then(() => nextGen())

应该这样做。

要将此概括为 N级,请选择上述任何方法,并行,然后递归:

let doGeneration = generation =>
  Promise.all(generation.map(child => loadChild(child))))
  .then(offsprings => offsprings && doGeneration(offsprings))

promiseParent.then(children => doGeneration(children));

因此,只要有更多要做的事情,你就可以通过resolving a promise with another promise进行扩展(这是你通过从.then履行处理程序返回一个新的承诺而隐含的做法。)