【问题标题】:Nodejs parallel with promiseNodejs 与 Promise 并行
【发布时间】:2016-03-15 21:13:21
【问题描述】:

我有一个这样的字典:

{go: ['went', 'run'], love: ['passion', 'like']}

键的值是它的同义词。 'getSynonymWords(word)' 是一个异步函数,它返回一个 promise,其中它的值是与传递的参数对应的同义词列表。如何遍历对象以递归方式获取另一个对象,如下所示:

{went: [], run: [], passion: [], like: []}

这是我的一段代码:

function getRelatedWords(dict) {
  return new Promise(function(resolve) {
    var newDict = {}; 
    for(var key in dict){
      if (dict.hasOwnProperty(key)) {
        var synonyms = dict[key];
        Promise.map(synonyms, function (synonym) {
          return getSynonymWords(synonym).then(function (synonyms) {
            newDict[synonym] = synonyms;
            return newDict;
          }); 
        }).then(function () {
          resolve(newDict);
        }); 
      }   
    }   
  }); 
}

这是不正确的,因为有些任务没有完成,但我不知道如何运行与承诺并行嵌套的任务。我正在使用蓝鸟库。你能帮帮我吗?

【问题讨论】:

  • javascript 是单线程的——所以没有parallel
  • 也许它是 bluebird 的一部分,我不知道,但 Promise.map 不是 vanilla JS 中的函数。
  • @BrandonNozakiMiller - 蓝鸟有很多糖
  • @JaromandaX 谢谢,我会避免这个。
  • 看起来你需要对Promise.map 的结果做点什么。将其添加到数组中,然后 for 循环完成后返回Promise.all(arrayOfPromiseMapResults)。这也将否定您对new Promise 的需求,这有点像an anti-pattern

标签: javascript node.js asynchronous promise bluebird


【解决方案1】:

首先,避免显式构造。现在我们已经结束了——我们可以通过首先获取所有单词,然后获取所有同义词,然后将它们折叠回字典,从而在没有嵌套和 4 行代码的情况下做到这一点。

function getRelatedWords(dict) {
   // first we get all the synonyms
   var synonyms = Object.keys(dict).map(x => dict[x]).reduce((p, c) => p.concat(c), []);
   // second we get all the synonyms for each word with the word itself
   var withSynonyms = Promise.map(synonyms, s => Promise.all([s, getSynonymWords(s)]));
   // then we fold it back to an object with Promise.reduce
   var asDict = withSynonyms.reduce((p, c) => p[c[0]] = c[1]), {});
   // and return it
   return asDict; 
}

如果我们想变得“聪明”,我们可以选择单行,我将在这里使用 ES2016 来娱乐:

let {entries} = Object;
let {reduce, all} = Promise;
const getRelatedWords = dict => reduce(entries(dict), (p, c) => p.concat(c), []).map(s => [s, getSynonymWords(s)]).map(all).reduce((p, [s, syns]) => p[s] = syns, {});

顺便说一句,更好的解决方案可能是使用 wordnet 之类的东西,它可以让您指定距离并进行一次呼叫。

【讨论】:

  • 非常感谢。你的代码太漂亮了。但我有一个问题,如何确保在获得asDict 之前执行所有getSynonymWords
  • @nguyenngoc101 我使用的是Promise.reduce,而不是reduce,如果它们是承诺,它会等待值(这是一种蓝鸟方法)。我将对其进行编辑以使用非静态版本,因为这样会更好一些。
猜你喜欢
  • 2017-01-09
  • 2018-02-08
  • 2017-06-16
  • 2015-11-14
  • 1970-01-01
  • 2016-02-17
  • 1970-01-01
  • 2018-12-14
  • 2016-04-23
相关资源
最近更新 更多