Luk*_*vat 24 javascript node.js
我有一个带参数和回调的函数.它应该向远程API发出请求并根据参数获取一些信息.当它获得信息时,它需要将其发送到回调.现在,远程API有时无法提供.我需要我的功能继续尝试,直到它设法做到这一点然后用正确的数据调用回调.
目前,我在函数内部有以下代码,但我认为像while(!done
); 是不正确的节点代码.
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);
Run Code Online (Sandbox Code Playgroud)
我该怎么做正确的方法?
Dmi*_*eev 37
没有必要重新发明轮子......在这种情况下,您可以使用流行的异步实用程序库,"重试"方法.
// try calling apiMethod 3 times
async.retry(3, apiMethod, function(err, result) {
// do something with the result
});
// try calling apiMethod 3 times, waiting 200 ms between each retry
async.retry({times: 3, interval: 200}, apiMethod, function(err, result) {
// do something with the result
});
Run Code Online (Sandbox Code Playgroud)
dc5*_*dc5 24
绝对不是要走的路 - 而(完成); 将进入一个硬循环并占用你所有的CPU.
相反,你可以做这样的事情(未经测试,你可能想要实现某种退避):
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...
});
Run Code Online (Sandbox Code Playgroud)
我发现Dmitry使用异步实用程序库的答案非常有用,也是最好的答案.
这个答案将他的例子扩展到定义apiMethod函数的工作版本并向其传递一个参数.我打算将代码添加为注释,但单独的答案更清晰.
const async = require('async');
const apiMethod = function(uri, callback) {
try {
// Call your api here (or whatever thing you want to do) and assign to result.
const result = ...
callback(null, result);
} catch (err) {
callback(err);
}
};
const uri = 'http://www.test.com/api';
async.retry(
{ times: 5, interval: 200 },
function (callback) { return apiMethod(uri, callback) },
function(err, result) {
if (err) {
throw err; // Error still thrown after retrying N times, so rethrow.
}
});
Run Code Online (Sandbox Code Playgroud)
重试文档:https://caolan.github.io/async/docs.html#retry
注意,在任务中调用apiMethod(uri,callback)的替代方法是使用async.apply:
async.retry(
{times: 5, interval: 200},
async.apply(task, dir),
function(err, result) {
if (err) {
throw err; // Error still thrown after retrying N times, so rethrow.
}
});
Run Code Online (Sandbox Code Playgroud)
我希望这为某人提供了一个很好的复制/粘贴锅炉板解决方案.
这是你想要做的吗?
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);
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
37365 次 |
最近记录: |