Asynchrone en parallèle des demandes sont en cours d'exécution de façon séquentielle

Je suis en cours d'exécution d'un serveur à l'aide de Node.js et la nécessité de demander des données à partir d'un autre serveur que je suis en cours d'exécution (localhost:3001). J'ai besoin de faire de nombreuses demandes (~200) pour le serveur de données et de collecte de données (réponse varient de ~20Kb à ~20 mo). Chaque demande est indépendante, et je voudrais enregistrer les réponses comme un tableau géant de la forme:

[{"urlAAA": responseAAA}, {"urlCCC": responseCCC}, {"urlBBB": responseBBB}, etc ]

Notez que l'ordre des éléments sans importance, ils devraient idéalement compléter le tableau dans l'ordre que les données deviennent disponibles.

var express = require('express');
var router = express.Router();
var async = require("async");
var papa = require("papaparse");
var sync_request = require('sync-request');
var request = require("request");
var pinnacle_data = {};
var lookup_list = [];
for (var i = 0; i < 20; i++) {
lookup_list.push(i);
}
function write_delayed_files(object, key, value) {
object[key] = value;
return;
}
var show_file = function (file_number) {
var file_index = Math.round(Math.random() * 495) + 1;
var pinnacle_file_index = 'http://localhost:3001/generate?file=' + file_index.toString();
var response_json = sync_request('GET', pinnacle_file_index);
var pinnacle_json = JSON.parse(response_json.getBody('utf8'));
var object_key = "file_" + file_number.toString();
pinnacle_data[object_key] = pinnacle_json;
console.log("We've handled file:    " + file_number);
return;
};
async.each(lookup_list, show_file, function (err) {});
console.log(pinnacle_data);
/* GET contact us page. */
router.get('/', function (req, res, next) {
res.render('predictionsWtaLinks', {title: 'Async Trial'});
});
module.exports = router;

Maintenant, lorsque ce programme est exécuté, il affiche:

We've handled file:    0
We've handled file:    1
We've handled file:    2
We've handled file:    3
We've handled file:    4
We've handled file:    5
etc

Maintenant que les fichiers sont de taille variable, je m'attendais à ce que ce serait d'effectuer les requêtes "en parallèle", mais il semble fonctionner de manière séquentielle, ce qui est ce que j'essayais de l'éviter grâce à l'aide de async.each(). Actuellement, il faut environ 1-2s pour se connecter au serveur de données et donc d'effectuer cette sur de nombreux fichiers est trop longue.

Je me rends compte que je suis en utilisant synchrone de la demande, et donc aimerais idéalement remplacer:

var response_json = sync_request('GET', pinnacle_file_index);

avec quelque chose de similaire à

request(pinnacle_file_index, function (error, response, body) {
if (!error && response.statusCode == 200) {
pinnacle_data[object_key] = JSON.parse(body);
}
});

Toute aide serait grandement appréciée.

En outre, j'ai regardé à essayer:

  • La conversion de la liste des url dans une liste de fonctions anonymes et à l'aide de async.parallel(function_list, function (err, results) { //add results to pinnacle_data[]});. (J'ai rencontré des problèmes en essayant de définir des fonctions uniques pour chaque élément du tableau).

De même, j'ai regardé les autres sujets connexes:

EDIT - SOLUTION DE TRAVAIL


Le code suivant n'est désormais la tâche (en prenant ~80ms par la demande, y compris pour faire des demandes répétées à l'aide de npm requestretry). De même, ce écailles très bien, en prenant une moyenne de temps de demande de ~80ms pour faire entre 5 demande au total, jusqu'à 1000.

var performance = require("performance-now");
var time_start = performance();
var async = require("async");
var request_retry = require('requestretry');
var lookup_list = [];
var total_requests = 50;
for (var i = 0; i < total_requests; i++) {
lookup_list.push(i);
}
var pinnacle_data = {};
async.map(lookup_list, function (item, callback) {
var file_index = Math.round(Math.random() * 495) + 1;
var pinnacle_file_index = 'http://localhost:3001/generate?file=' + file_index;
request_retry({
url: pinnacle_file_index,
maxAttempts: 20,
retryDelay: 20,
retryStrategy: request_retry.RetryStrategies.HTTPOrNetworkError
},
function (error, response, body) {
if (!error && response.statusCode == 200) {
body = JSON.parse(body);
var data_array = {};
data_array[file_index.toString()] = body;
callback(null, data_array);
} else {
console.log(error);
callback(error || response.statusCode);
}
});
},
function (err, results) {
var time_finish = performance();
console.log("It took " + (time_finish - time_start).toFixed(3) + "ms to complete " + total_requests + " requests.");
console.log("This gives an average rate of " + ((time_finish - time_start) / total_requests).toFixed(3) + " ms/request");
if (!err) {
for (var i = 0; i < results.length; i++) {
for (key in results[i]) {
pinnacle_data[key] = results[i][key];
}
}
var length_array = Object.keys(pinnacle_data).length.toString();
console.log("We've got all the data, totalling " + length_array + " unique entries.");
} else {
console.log("We had an error somewhere.");
}
});

Merci pour l'aide.

OriginalL'auteur oliversm | 2015-09-07