5

Background

I usually write node.js script based on async.js to control the work flow. Sometimes I found that based on async.js, the code seems still a 'hell'. With multiple nest the code is not readable and tricky to maintain. I did some search here and found some useful resources - but most of them are general concepts. So I am going to ask a question. Any feedback would be appreciated.

My common code

var request = require('request');
var async = require('async');

var array = [1, 2, 3, 4 ,5 ,6];
var url = 'http://www.google.com';
async.mapLimit(array, 3, function(number, callback) {
       request(url + number, function(error, res, body){
                  //do sth
                 callback();
       });
}, function(err){//do nothing});

Question

So this time I want to replace this kind of code by Promise. Could you please help? If the question is duplicated, please suggest some useful resource url. Thanks!

10
  • Where is url defined? Do you want to process only first three elements in array array? Commented Sep 27, 2016 at 7:18
  • @guest271314 Hey, thanks for your attention. Url can be any string, it's not important here. For your second question, do you really know about async.js? Commented Sep 27, 2016 at 7:21
  • 1
    You can use Promise and Promise.all() method to resolve this issue Commented Sep 27, 2016 at 7:22
  • 1
    @J.Lyu you either write your own concurrency limiting, or use alternative Promise implementation like Bluebird, it has concurrency option. With HTTP requests to same URL you can use node's Agent class to limit number of concurrent requests to the same host. Commented Sep 27, 2016 at 7:33
  • 1
    I would advise you to consider using Bluebird powered request-promise or native ES6 promises powered request-promise-native in the first place. Commented Sep 27, 2016 at 8:23

1 Answer 1

5

You will need to Promisify request, which can be done with native promises, but since you're using NodeJS, it would be preferable if you used the Bluebird promise library, which is almost strictly superior to the native implementation.

Then you can do:

const Promise = require('bluebird');
const requestAsync = Promise.promisify(request); // This is what bluebird saves you
// requestAsync returns a promise instead of accepting a callback.

const array = [1, 2, 3, 4, 5, 6];

const requestSingle = number => requestAsync(`${url}${number}`);

Promise.map(array, requestSingle, {concurrency: 3});

Note that Promise.map() is a Bluebird functionality, and not native.

The closest you can easily get with native is:

const arrayOfRequestPromises = array.map(requestSingle);

Promise.all(arrayOfRequestPromises)
  .then(allResults => {
    // do something
  })
  .catch(err => {
    // handle errors
  });

But then you lose the maximum 3 concurrent requests option.

Sign up to request clarification or add additional context in comments.

7 Comments

Thanks for MadaraUchiha, i will try on my side then let you know if it works well. Btw thank @jfriend00
Why do you have array.requestSingle?
@jfriend00 Typo, this is too early in the morning for me.
How do I implement following logic: #1 after connecting to google.com1, fetch the html, then save to 1.html after connecting to google.com2, fetch the html, then save to 2.html ... #2 In my async.js code, i can set timeout before callback. In other word, I will have some seconds' delay during each 3 items running. Can this be implemented here? Thanks
@J.Lyu It can (and look good too!), but that's a bit broad for an answer on Stack Overflow, you should look into the Promise primitive, and how it abstracts asynchronous values. Promises are highly composable, you can wait for the first of N promises (implementing a timeout), and wait for the result of all promises (creating a waiting point for synchronization), you can use .then() to create chains of Promises, and you can do all those things together.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.