javascriptasynchronouspromisesynchronousco

Javascript.Run Multi promises Synchronously


I want to request a website for 40 times.

I want this to be synchronously, like 10 requests 4 times.

This is My code for 1 request - 40 times:

'use strict';

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


function callUrl(url) {
    return new Promise((resolve, reject) => {
        request.get(url, (e, r, b) => {
            if (e) reject(e)
            else
                resolve(`Response from ${url}`);
        });
    })
}


co(function*() {
        for (var i = 1; i < 41; i++) {
            let rs = yield callUrl('https://www.google.com/?q=' + i);
            // let rs = yield makeUrls(10,i);
            console.log(rs);
        }
    });

I can make an array of promises, but I can't figure it out how to change the value of q to be different.


Solution

  • You don't want to run them synchronously - you want to synchronize them - those are different.

    You'd use an array of promises together with Promise#all. When you create a promise the action is already being executed - only yield synchronizes things.

    You can make 10 requests at once like so:

    co(function*() {
        for (var i = 1; i < 41;) {
            var promises = [];
            for(var lim = i + 10; i < Math.max(lim, 41); i++) {
               promises.push(callUrl('https://www.google.com/?q=' + i));
            }
            let rs = yield Promise.all(promises); // wait for everything
            console.log(rs); // an array of 10 results
    });
    

    Note that in addition to that, your code is still not very efficient - what happens if 9 out of 10 requests are really fast and one takes a minute? You'll only have one outgoing requests. You can use a library like bluebird which has a more efficient Promise.map method with a concurrency parameter.