I have a dict like this:
{go: ['went', 'run'], love: ['passion', 'like']}
The value of a key is its synonyms. And 'getSynonymWords(word)' is a async function that returns a promise in which Its value is a list of synonym words corresponding with the parameter passed. How can I loop through the object to get another object recursively like this:
{went: [], run: [], passion: [], like: []}
This is my piece of code:
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);
});
}
}
});
}
It is incorrect because some tasks are not finished, But I don't know how to run tasks parallel nested with promises. I'm using Bluebird library. Could you help me?
So, yes, the V8 implementation if you will. Promises cannot "be executed". They start their task when they are being created - they represent the results only - and you are executing everything in parallel even before passing them to Promise.
As you can see, Promise. all executes code concurrently, but what is parallel execution? JavaScript is single-threaded and can only perform a single chunk of work at a time, so parallel execution is not possible with JavaScript, except for some circumstances such as web workers.
So, to run all these APIs in parallel, we can use Promise. all() like so. As you can tell, now we're running all the three APIs in parallel through Promise. all() through a single await .
The Promise.all() method takes an iterable of promises as an input, and returns a single Promise that resolves to an array of the results of the input promises. This returned promise will fulfill when all of the input's promises have fulfilled, or if the input iterable contains no promises.
First of all, avoid explicit construction. Now that we're over that - we can do this with no nesting and 4 lines of code by first getting all the words, then getting all the synonyms, then folding them back to a dictionary.
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;
}
If we wanted to be "clever" we can opt to a one liner, I'm going to use ES2016 here for fun:
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, {});
The better solution btw is probably to use something like wordnet that lets you specify the distance and make a single call.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With