如何做重复的请求,直到一个成功没有在节点阻塞?

我有一个函数,需要一个参数和callback。 它应该做一个删除API的请求,并获取一些基于参数的信息。 当它得到的信息,它需要发送到callback。 现在,远程API有时无法提供。 我需要我的function继续尝试,直到它设法做到这一点,然后用正确的数据调用callback。

目前,我有这个

var history = {}; while (true) { var done = false; var retry = true; var req = https.request(options, function (res) { var acc = ""; res.on("data", function(msg){ acc += msg.toString("utf-8"); }); res.on("end", function () { done = true; history = JSON.parse(acc); if (history.success) { retry = false; } }); }); req.end(); while (!done) ; if (!retry) break; } callback(history); 

里面的function,但我认为这样的东西(!完成); 是不正确的节点代码。

我如何以正确的方式做到这一点?

绝对不是要走的路 – 当(!完成); 将进入一个艰难的循环,并占用所有的CPU。

相反,你可以做这样的事情(未经testing,你可能想实现某种退缩):

 function tryUntilSuccess(options, callback) { var req = https.request(options, function(res) { var acc = ""; res.on("data", function(msg) { acc += msg.toString("utf-8"); }); res.on("end", function() { var history = JSON.parse(acc); //<== Protect this if you may not get JSON back if (history.success) { callback(null, history); } else { tryUntilSuccess(options, callback); } }); }); req.end(); req.on('error', function(e) { // Decide what to do here // if error is recoverable // tryUntilSuccess(options, callback); // else // callback(e); }); } // Use the standard callback pattern of err in first param, success in second tryUntilSuccess(options, function(err, resp) { // Your code here... }); 

没有必要重新发明轮子…在这种情况下,您可以使用常用的asynchronous实用程序库“重试”方法。

 async.retry(3, apiMethod, function(err, result) { // do something with the result }); 

asynchronousGitHub页面

async.retry文档

这是你正在尝试做什么?

 var history = {}; function sendRequest(options, callback) { var req = https.request(options, function (res) { var acc = ""; res.on("data", function (msg) { acc += msg.toString("utf-8"); }); res.on("end", function () { history = JSON.parse(acc); if (history.success) { callback(history); } else { sendRequest(options, callback); } }); }); req.end(); } sendRequest(options, callback); 

我已经使用重试模块解决了这个问题。

例:

 var retry = require('retry'); // configuration var operation = retry.operation({ retries: 2, // try 1 time and retry 2 times if needed, total = 3 minTimeout: 1 * 1000, // the number of milliseconds before starting the first retry maxTimeout: 3 * 1000 // the maximum number of milliseconds between two retries }); // your unreliable task var task = function(input, callback) { Math.random() > 0.5 ? callback(null, 'ok') // success : callback(new Error()); // error } // define a function that wraps our unreliable task into a fault tolerant task function faultTolerantTask(input, callback) { operation.attempt(function(currentAttempt) { task(input, function(err, result) { console.log('Current attempt: ' + currentAttempt); if (operation.retry(err)) { // retry if needed return; } callback(err ? operation.mainError() : null, result); }); }); } // test faultTolerantTask('some input', function(err, result) { console.log(err, result); }); 

你可以尝试以下几行。 我正在写一个大概的想法,你应该用你的HTTP请求replacetrySomething。

 function keepTrying(onSuccess) { function trySomething(onSuccess, onError) { if (Date.now() % 7 === 0) { process.nextTick(onSuccess); } else { process.nextTick(onError); } } trySomething(onSuccess, function () { console.log('Failed, retrying...'); keepTrying(onSuccess); }); } keepTrying(function () { console.log('Succeeded!'); }); 

我希望这有帮助。

名为Flashheart的图书馆也是一个合适的select。 这是一个rest客户端devise,易于使用和支持重试。

例如,configurationFlashheart重试10次,请求之间的延迟时间为500毫秒:

 const client = require('flashheart').createClient({ retries: 10, retryTimeout: 500 }); const url = "https://www.example.com/"; client.get(url, (err, body) => { if (err) { console.error('handle error: ', err); return; } console.log(body); }); 

有关更多信息,请查看文档: https : //github.com/bbc/flashheart

免责声明:我对这个图书馆有所贡献。