简体   繁体   中英

Multiple http post calls in foreach with nodejs

How can I execute many request in foreach without error please ?

Currently, I send a request on each entry on my array with foreach :

users.forEach(function (user) {
    request({
        url   : 'myurl.com/api',
        method: 'POST',
        auth  : {
            'bearer': CONFIGURATION.auth.token
        },
        body  : {
            sender_id: user.sender_id
        },
        json  : true
    }, function (error, response, body) {
        if (!error && response.statusCode === 200) {
            resolve(body);
        } else {
            console.log('Error on coreService');

            console.log('############### ERROR ###############');
            console.log(error);
            console.log('############### BODY ###############');
            console.log(body);
            console.log('############### RESPONSE ###############');
            console.log(response);

            reject(error);
        }
    });
});

With some request it's ok, but with some request I have this error :

Error on coreService
############### ERROR ###############
{ Error: connect ECONNRESET 127.0.0.1:80
    at Object._errnoException (util.js:1022:11)
    at _exceptionWithHostPort (util.js:1044:20)
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1198:14)
  code: 'ECONNRESET',
  errno: 'ECONNRESET',
  syscall: 'connect',
  address: '127.0.0.1',
  port: 80 }
############### BODY ###############
undefined
############### RESPONSE ###############
undefined

Do you have an idea how can I fix this problem please ?

I tried with :

server.timeout = 0;

or

server.timeout = 1000;

but same problem...

If I execute the request, user by user, it's fine ! But with the foreach, it's break on some request...

In the comments colinux proposes that the connection reset errors are due to the server protecting itself from too many simultaneous requests, and I think they are probably correct. This code shows how you can use async/await to make your requests to the server one at a time. This might be too slow for you, but it could help you to confirm that the problem is as explained by colinux.

Here is another answer which does not require the use of request-promise-native and instead wraps the request calls in its own Promise.

const request = require('request');
const users = [{sender_id: 1}, {sender_id: 2}, {sender_id: 3}];

// make this driver function async so we can use await which allows waiting for
// a request to finish before starting the next one

async function runUserRequests() {
    for (let i = 0; i < users.length; i++) {
        const user = users[i];
        try {
            const response = await requestPromise(user);
            console.log("response for user", user, response);
        } catch (error) {
            console.log("error for user", user, error);
        }
    };
}

// wrap the request call in a Promise so that it will run synchronously
function requestPromise(user) {
    return new Promise(function(resolve, reject) {
        request({
            url: 'http://localhost:4000/',
            method: 'GET', // method 'POST'
            // auth  : {
            //     'bearer': CONFIGURATION.auth.token
            // },
            // body  : {
            //     sender_id: user.sender_id
            // },
            // json  : true
        }, function (error, response, body) {
            if (!error && response.statusCode === 200) {
                resolve(body);
                console.log("request successful for user", user, " at ", (new Date()).getTime());
            } else {
                console.log('Error on coreService');

                console.log('############### ERROR ###############');
                console.log(error);
                console.log('############### BODY ###############');
                console.log(body);
                console.log('############### RESPONSE ###############');
                console.log(response);

                reject(error);
            }
        });
    });
}

runUserRequests();

/* 
Sample server used to test the code above:

const express = require('express')
const app = express()
const port = 4000

app.get('/', (req, res) => {
    console.log("spinning for a bit");
    setTimeout( () =>  {
        console.log("  now responding");
        res.send('Hello World!');
    }, 1000);
});

app.listen(port, () => console.log(`Example app listening on port ${port}!`))

*/


In the comments colinux proposes that the connection reset errors are due to the server protecting itself from too many simultaneous requests, and I think they are probably correct. This code shows how you can use async/await to make your requests to the server one at a time. This might be too slow for you, but it could help you to confirm that the problem is as explained by colinux.

To get this to work you'll need to install request-promise-native. If you can't do that let me know and I can work up an example wrapping the request api in your own Promise.

const request = require('request-promise-native');
//const users = [1, 2, 3, 4]; // dummy user array for testing
async function runUserRequests(users) {
    for (let i = 0; i < users.length; i++) {
        const user = users[i];
        console.log("starting request for user ", user);
        await request({
            url: 'http://localhost:4000/',
            method: 'GET',
            auth  : {
                 'bearer': CONFIGURATION.auth.token
            },
            body  : {
                sender_id: user.sender_id
            },
            json  : true
        }, function (error, response, body) {
            if (!error && response.statusCode === 200) {
                console.log("request successful for user", user, " at ", (new Date()).getTime());
                resolve(body);
            } else {
                console.log('Error on coreService');

                console.log('############### ERROR ###############');
                console.log(error);
                console.log('############### BODY ###############');
                console.log(body);
                console.log('############### RESPONSE ###############');
                console.log(response);

                reject(error);
            }
        });
    };
}

runUserRequests();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM