JavaScript Promises:使用 Breadth-First 遍历递归构建 Promise 链

JavaScript Promises: Recursively Building Promise Chain With Breadth-First Traversal

原生JavascriptES5/ES6承诺

我正在尝试导入具有递归关系的数据,因为 数据库(mongodb)正在分配 ID - 必须(异步地)加载 parent 在 children 可以加载之前(也是异步的)。

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

任务 A - 一些过程

任务 B - 递归异步加载(bread-first遍历)

任务 C - 依赖于任务 B

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

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

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

我想它会像 breadth-first 队列一样遍历(我最好 尽可能避免使用队列数据结构)

我发现这个很难破解。任何建议或 解决方案?

Promise 链可以动态扩展,在链中的任何点插入新链接,只需 return 任何 .then 履行处理程序的承诺。

假设每个任务都用其 children 的数组来解析。如果children可以并行处理,那么:

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

应该可以。如果children必须按顺序处理,那么:

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 知道 return 下一代来简化)。

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

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

因此,只要有更多事情要做,您始终可以通过 进行扩展(这就是您通过 return 从 .then 实现中获得新承诺而隐含地做的事情处理程序)。