我使用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();
}
上面,返回多个回调的风险很大,一个来自正常的流程代码(如果任务成功完成),一个来自setTimeout。
我的问题是:有没有更好的方法来避免这种情况。导致当前解决方案可能会返回两个回调。我收到了以下错误:"已经调用了回调。"
答案 0 :(得分:1)
您可以设置一个标志,表明您是否已经调用了回调。你可以将它放在你的async.map()
处理程序中:
let called = false;
function doCallback(err, data) {
if (!called) {
called = true;
callback(err, data);
}
}
然后,在doCallback()
处理程序中使用async.map()
而不是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
}