Nodejs中如何处理一个函数下多次回调的风险
How to handle risk of multiple callbacks under one function in Nodejs
我正在使用async.map处理多个任务,我想为每个任务设置一个超时时间。
async.map(tasks, handleFunction, (error, callback))
I add the setTimeout inside handleFunction to return immediately,
const handleFunction = function(callback){
setTimeout(()=> {return setImmediate(callback, new Error())});
// handler logic, detail process code ...
// some http requests or file read and
return callback();
}
以上,return调用多个回调是有风险的,一个来自正常流程代码(如果任务成功完成),一个来自setTimeout。
我的问题是:有没有更好的方法来避免这种情况。导致目前解决方案可能return两次回调。我收到以下错误:"Callback was already called."
你可以只设置一个标志来判断你是否已经调用了回调。您可以将其放入 async.map()
处理程序中:
let called = false;
function doCallback(err, data) {
if (!called) {
called = true;
callback(err, data);
}
}
然后,在您的 async.map()
处理程序中使用 doCallback()
而不是 callback()
。如果你多次调用 doCallback()
,它什么都不做。只有对其的第一次调用才会传递到实际的异步回调。
如果您展示了包含所有详细信息的实际代码,我们还可以建议一种编码方法,如果您在定时器关闭之前调用回调并且定时器确实触发,则在定时器触发之前取消定时器,然后设置一个您已经超时的标志,以便您可以在事情完成后调用 callback()
之前检查该标志。
您也可以自己制作一个回调超时实用程序函数,您可以在需要此类功能的任何地方重新使用它。
// callback that times out
function timerCallback(t, timeoutErr, callback) {
let called = false;
let timer = setTimeout(() => {
if (!called) {
called = true;
callback(timeoutErr);
}
}, t);
return function(err, data) {
clearTimeout(timer);
if (!called) {
called = true;
callback(err, data);
}
};
}
然后您将像这样使用它:
async.map(tasks, handleFunction, (error, callback))
// create callback with debouncing and timeout
let internalCallback = timerCallback(1000, new Error("timeout"), callback);
// then do your async stuff and call internalCallback(err, data) when done
}
我正在使用async.map处理多个任务,我想为每个任务设置一个超时时间。
async.map(tasks, handleFunction, (error, callback))
I add the setTimeout inside handleFunction to return immediately,
const handleFunction = function(callback){
setTimeout(()=> {return setImmediate(callback, new Error())});
// handler logic, detail process code ...
// some http requests or file read and
return callback();
}
以上,return调用多个回调是有风险的,一个来自正常流程代码(如果任务成功完成),一个来自setTimeout。
我的问题是:有没有更好的方法来避免这种情况。导致目前解决方案可能return两次回调。我收到以下错误:"Callback was already called."
你可以只设置一个标志来判断你是否已经调用了回调。您可以将其放入 async.map()
处理程序中:
let called = false;
function doCallback(err, data) {
if (!called) {
called = true;
callback(err, data);
}
}
然后,在您的 async.map()
处理程序中使用 doCallback()
而不是 callback()
。如果你多次调用 doCallback()
,它什么都不做。只有对其的第一次调用才会传递到实际的异步回调。
如果您展示了包含所有详细信息的实际代码,我们还可以建议一种编码方法,如果您在定时器关闭之前调用回调并且定时器确实触发,则在定时器触发之前取消定时器,然后设置一个您已经超时的标志,以便您可以在事情完成后调用 callback()
之前检查该标志。
您也可以自己制作一个回调超时实用程序函数,您可以在需要此类功能的任何地方重新使用它。
// callback that times out
function timerCallback(t, timeoutErr, callback) {
let called = false;
let timer = setTimeout(() => {
if (!called) {
called = true;
callback(timeoutErr);
}
}, t);
return function(err, data) {
clearTimeout(timer);
if (!called) {
called = true;
callback(err, data);
}
};
}
然后您将像这样使用它:
async.map(tasks, handleFunction, (error, callback))
// create callback with debouncing and timeout
let internalCallback = timerCallback(1000, new Error("timeout"), callback);
// then do your async stuff and call internalCallback(err, data) when done
}