Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
175 views
in Technique[技术] by (71.8m points)

Javascript - how to control how many promises access network in parallel

in my application, I have and array of promises that access network in parallel, but some times, when my app is running full speed, my network slows down, due to many promises accessing network, I would like to know how I could control how many access network in parallel. This is a sample of code:

var ids = {1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 6: 56, 7: 7, 8: 8, 5:6 }; // this is random 
Promise.all( Object.keys(ids).map(function(dp){
  return new Promise(function(resolve, reject){

       http.post({url: addr, form: { data: dp }}, function(err, res, body){
        if (err){
            reject(err)
        }            
        resolve(body.xx);
      });

  });
})).then(function(data){
       http.post({url: hostAddress, form: { data: data.x }}, function(err, res, body){
        ......
        resolve(body.xx);
      });    
});
  });
}))

There are a lot of networking. I would be great I could allow only 2 or 3 at the same time. Thanks for your help.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can use Bluebird's .map() which has a concurrency option to control how many requests are in-flight at the same time:

const Promise = require('bluebird');
const http = Promise.promisifyAll(require('http');

var ids = {1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 6: 56, 7: 7, 8: 8, 5:6 }; // this is random 

Promise.map(Object.keys(ids).map(function(dp){
    return  http.post({url: addr, form: { data: dp }).then(function(body) {
        return body.xx;
    });
}), {concurrency: 2}).then(function(results) {
    // process results here
});

FYI, I didn't understand what you were trying to do with your second http.post() because you where referencing data.x when data is an array. I think the code is a bit too much pseudo-code to illustrate what you were really trying to do with that second http.post().


Otherwise, you can code your own concurrency control where you fire up N requests initially and then each time one finishes, you fire up another until you have no more to do. Here's an example of coding the concurrency control manually:

Fire off 1,000,000 requests 100 at a time

Or, you could write it yourself like this:

const http = require('http');

function httpPost(options) {
    return new Promise(function(resolve, reject) {
        http.post(options, function(err, res, body) {
            if (err) {
                reject(err);
            } else {
                resolve(body);
            }
        });
    });
}

// takes an array of items and a function that returns a promise
function mapConcurrent(items, maxConcurrent, fn) {
    let index = 0;
    let inFlightCntr = 0;
    let doneCntr = 0;
    let results = new Array(items.length);
    let stop = false;

    return new Promise(function(resolve, reject) {

        function runNext() {
            let i = index;
            ++inFlightCntr;
            fn(items[index], index++).then(function(val) {
                ++doneCntr;
                --inFlightCntr;
                results[i] = val;
                run();
            }, function(err) {
                // set flag so we don't launch any more requests
                stop = true;
                reject(err);
            });
        }

        function run() {
            // launch as many as we're allowed to
            while (!stop && inflightCntr < maxConcurrent && index < items.length) {
                runNext();
            }
            // if all are done, then resolve parent promise with results
            if (doneCntr === items.length) {
                resolve(results);
            }
        }

        run();
    });
}

var ids = {1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 6: 56, 7: 7, 8: 8, 5:6 }; // this is random 


mapConcurrent(Object.keys(ids), 2, function(item, index) {
    return httpPost({url: addr, form: {data: item}}).then(function(body) {
        return body.xxx;
    });
}).then(function(results) {
    // array of results here
}, function(err) {
    // error here    
});

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...