❤️ OSS, I share software development know-how & contribute to the projects I rely on (and admire) most: @nodejs @lodash @mongodb @docker @minio @bluebird et al.
Excellent article, I only have one suggestion.
Avoid using either .forEach or .reduce for sequential promise execution - at least when overwriting references to the promises.
Either use plain function recursion, or use a lib like bluebird.
Bluebird has features builtin for exactly this situation, including .mapSeries and concurrent execution limits, like .map(fn, {concurrency: CPU_COUNT})
Example with Bluebird:
constPromise=require('bluebird')constsearchTerms=(terms)=>Promise.resolve(terms).map(q=>`http://httpbin.org/get?${q}`)// transform to needed func params for next step(s).tap(url=>console.time('Load %s',url))// Easy to add/remove metrics.mapSeries(url=>fetch(url)// -> Nested dependent logic:.then(resp=>resp.json())// unpack JSON.then(resp=>{// Final stepleturl=resp.url;console.timeEnd('Load %s',url);returnresp.url;// {url: resp.url, body: resp.body};}))searchTerms(['ahoy','hello','hallo']).then(allUrls=>{console.log('Successfully loaded URL(s):',allUrls)).catch(error=>console.error('A call failed:',error.message))
I'm a developer, product manager and public speaker based in the SF Bay Area. I'm passionate for JavaScript, the web, hackathons, teaching, photography & cocktails.
Good point! I mainly wanted to explain how to handle it without the help of an additional tool in a still elegant solution. I think a recursive function wouldn't make it too readable. But yeah I agree that you should ideally use something that is a bit more sophisticated. Bluebird is certainly a good solution for this.
❤️ OSS, I share software development know-how & contribute to the projects I rely on (and admire) most: @nodejs @lodash @mongodb @docker @minio @bluebird et al.
Excellent article, I only have one suggestion.
Avoid using either
.forEach
or.reduce
for sequential promise execution - at least when overwriting references to the promises.Either use plain function recursion, or use a lib like bluebird.
Bluebird has features builtin for exactly this situation, including
.mapSeries
and concurrent execution limits, like.map(fn, {concurrency: CPU_COUNT})
Example with Bluebird:
Good point! I mainly wanted to explain how to handle it without the help of an additional tool in a still elegant solution. I think a recursive function wouldn't make it too readable. But yeah I agree that you should ideally use something that is a bit more sophisticated. Bluebird is certainly a good solution for this.
Also, another example of bluebird features,
promisify
existing callback-based libs using a common method.So to read a file w/ Promises, use: