简体   繁体   English

具有承诺和并发性的递归

[英]Recursion with promises and concurrency

Bear with me, because this takes some setting out.请耐心等待,因为这需要一些设置。

Consider this trivial tree of values, for the purpose of the question / discussion.出于问题/讨论的目的,考虑这个平凡的价值树。

const valuetree = [{
    item: 1,
    value: 100,
  },
  {
    item: 2,
    value: [{
      item: 3,
      value: [{
          item: 4,
          value: 200
        },
        {
          item: 5,
          value: 200
        },
        {
          item: 6,
          value: 200
        },
      ]
    }]
  },
];

Now if we wanted to write a recursive function to add up all the values, then this in itself is fairly trivial.现在,如果我们想编写一个递归 function 来将所有值相加,那么这本身就相当简单。 Like so:像这样:

function sumTree(leaf) {
  let total = 0;

  if (Array.isArray(leaf)) {
    leaf.forEach(subLeaf => {
      total += sumTree(subLeaf);
    });
  } else {
    if (Array.isArray(leaf.value)) {
      total += sumTree(leaf.value);
    } else {
      total += Number(leaf.value);
    }
  }

  return total;
}

Now suppose we want to use promises to achieve the same thing?现在假设我们想使用 Promise 来实现同样的事情?

This is what I end up with...这就是我最终的结果......

async function sumTreeAsync(leaf) {
  let promises = [];

  if (Array.isArray(leaf)) {
    leaf.forEach(async subLeaf => {
      promises.push(sumTreeAsync(subLeaf));
    });
  } else {
    if (Array.isArray(leaf.value)) {
      promises.push(sumTreeAsync(leaf.value));
    } else {
      promises.push(leaf.value);
    }
  }

  return promises;
}

So what gets returned looks like this所以返回的内容看起来像这样

[ Promise { [ 100 ] }, Promise { [ [Promise] ] } ]

Which makes sense, an array of 2 top level items, a promise of a literal value, and a promise that returns a nested array of promises.这是有道理的,一个包含 2 个顶级项目的数组,一个字面值的 promise 和一个返回嵌套的承诺数组的 promise。

So now as some function like Promise.all only deals with a flat array of promises, I would have to recurse the nested promises to arrive at the same outcome.所以现在作为一些 function 像 Promise.all 只处理一个平面的承诺数组,我将不得不递归嵌套的承诺以达到相同的结果。 So now I have to recurse the tree twice, which just smells so bad.所以现在我必须递归这棵树两次,这闻起来很糟糕。

So perhaps I need to return resolved promises from the 2 cases where the subleaf is an array?所以也许我需要从 subleaf 是数组的 2 种情况中返回已解决的承诺?

Is it even worth doing this or should recursion just be synchronous?这样做是否值得,或者递归应该是同步的?

You're not far off.你不远了。 If you change your return to do a Promise.all call and .then (sum) for an obvious sum function, this would work:如果您将退货更改为执行Promise.all调用和 .then .then (sum)以获得明显的sum function,这将起作用:

 const sum = (ns) => ns.reduce ((a, b) => a + b, 0) async function sumTreeAsync(leaf) { let promises = []; if (Array.isArray(leaf)) { leaf.forEach(async subLeaf => { promises.push(sumTreeAsync(subLeaf)); }); } else { if (Array.isArray(leaf.value)) { promises.push(sumTreeAsync(leaf.value)); } else { promises.push(leaf.value); } } return Promise.all(promises).then(sum); } const valuetree = [{item: 1, value: 100}, {item: 2, value: [{item: 3, value: [{item: 4, value: 200}, {item: 5, value: 200}, {item: 6, value: 200}]}]}]; sumTreeAsync (valuetree).then (console.log)

But I would definitely write this code in a different way:但我肯定会以不同的方式编写这段代码:

 const sum = (ns) => ns.reduce ((a, b) => a + b, 0) const sumTreeAsync = async (leaf) => Promise.all (Array.isArray (leaf)? leaf.map (sumTreeAsync): Array.isArray (leaf.value)? [sumTreeAsync (leaf.value)]: [leaf.value] ).then (sum) const valuetree = [{item: 1, value: 100}, {item: 2, value: [{item: 3, value: [{item: 4, value: 200}, {item: 5, value: 200}, {item: 6, value: 200}]}]}]; sumTreeAsync (valuetree).then (console.log)

More than that.比那更多的。 I would probably not write this code at all.我可能根本不会写这段代码。 JS is still generally a single-threaded language. JS 一般还是单线程语言。 So you get no concurrent calculations at all in this approach.所以在这种方法中你根本不会得到并发计算。 If instead of your simple summation, you were handing things off to different workers to process, then it might make sense.如果您不是简单的总结,而是将事情交给不同的工作人员处理,那么这可能是有道理的。 As it is, this just feels like an unnecessary complication.事实上,这只是一种不必要的并发症。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM