2017-07-06 1 views
1

je suis en train de faire plusieurs requêtes HTTP et cumulat, afficher les résultats dans NodeJS en utilisant le code suivant:NodeJS Async - Poursuivre l'exécution de plusieurs requêtes http même si certains ne

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

function httpGet(url, callback) { 
    const options = { 
    url : url, 
    json : true 
    }; 
    request(options, 
    function(err, res, body) { 
     console.log("invoked") 
     callback(err, body); 
    } 
).on('error', function(err) { 
    console.log(err) 
    }); 
} 

const urls= [ 
    "http://1.2.3.4:30500/status/health/summary", 
    "http://5.6.7.8:30505/status/health/summary" 
]; 

async.map(urls, httpGet, function (err, res){ 
    if (err) 
    console.log(err); 
    else 
    console.log(res); 
}); 

Le problème ici est, si la première demande (http://1.2.3.4:30500/status/health/summary) échoue (comme connexion refusée, etc.), la seconde ne passe pas par. Je sais que je commets une erreur idiote mais je ne la trouve pas. Toute aide appréciée!

+0

Je pense que cela se produit parce que 'request' est synchrone. S'il vous plaît jeter un oeil https://www.npmjs.com/package/request-promise – hisener

+0

pourquoi ne pas u utilisé 'async.series'? sur le premier succès à pour l'autre. @hisener a raison. La fonction de demande est sync. –

+2

'request' _n'est pas synchrone! La sémantique de 'async.map()' est telle que lorsqu'une erreur survient, le callback final est appelé immédiatement. – robertklep

Répondre

2

Dans async.map si l'un des appels passe une erreur à son rappel, le rappel principal (pour la fonction de la carte) est immédiatement appelé avec l'erreur (c'est le problème dans votre cas). Afin de ne pas se terminer sur la première erreur, n'appelez pas le callback avec err param dans votre httpGet. Utilisez async chacun, il reçoit une liste d'arguments et une fonction, et appelle la fonction avec chaque élément, assurez-vous dans votre httpGet à l'intérieur sur l'erreur que vous appelez le rappel, sans l'erreur, cela fera le reste des appels pour continuer même s'il y avait une erreur dans certains des appels. Cela peut fonctionner pour carte mais aussi, je pense que la fonction plus adaptée à votre cas est async.each, au lieu de la carte, vous pouvez également limiter le nombre d'appels simultanés avec la méthode eachLimit.

Vérifier https://caolan.github.io/async/docs.html#each

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

function httpGet(url, callback) { 
    const options = { 
     url : url, 
     json : true 
    }; 
    request(options, 
     function(err, res, body) { 
      if (err){ 
       console.log(err); 
       callback(); 
       return; 
      } 
      console.log("invoked") 
      callback(null, body); 
     } 
    ).on('error', function(err) { 
     console.log(err); 
     callback(); 
    }); 
} 

const urls= [ 
    "http://1.2.3.4:30500/status/health/summary", 
    "http://5.6.7.8:30505/status/health/summary" 
]; 

async.each(urls, httpGet, function (err, res) { 
}, function (err, res) { 

}); 
0

Si vous voulez async.map ne pas manquer rapide, vous pouvez le faire comme ça

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

function httpGet(url, callback) { 
    const options = { 
    url : url, 
    json : true 
    }; 
    request(options, 
    function alwaysReportSuccess(err, res, body) { 
     callback(null, { 
     success: !err, 
     result: err ? err : body 
     }); 
    } 
).on('error', function(err) { 
    console.log(err) 
    }); 
} 

const urls= [ 
    "http://1.2.3.4:30500/status/health/summary", 
    "http://5.6.7.8:30505/status/health/summary" 
]; 

async.map(urls, httpGet, function alwaysOk(_, res){ 
    console.log(res); // will be an array with success flags and results 
});