@zengming00 不知道你的“本楼正解”是自己写的还是楼主改的,感觉你的思路与楼主的示例代码有些不符。楼主示例代码给人的感觉是要运行一系列任务,如果所有都在规定时间内完成了,结果是这一系列任务结果的一个集合;如果其中有任务超时了,到达查实时间后不会卡住也会返回结果,结果为其中已经执行好的任务结果的一个集合。而你给出的 Promise.race 的解决方案,只要有一个任务成功执行就会 resolve,这样结果中不会包含其他任务的执行结果;在所有任务都执行超时时才会触发附加的超时的 reject。
以下是我的一个思路,如果理解不对也请谅解。
根据自己最冲动最初始的想法写代码,可以满足要求,但是略显繁杂,在所有需要 callback 的地方都需要判断。
'use strict';
const async = require('async');
const list = [1, 2, 3, 4, 5, 6];
async.mapLimit(list, 10, function (item, callback) {
let alreadyCallback = false;
setTimeout(function () {
if (!alreadyCallback) {
callback(new Error('manual set error'));
return alreadyCallback = true;
} else {
// do nothing
}
}, 3000);
// // 超时任务
// if (item === 3) {
// setTimeout(function () {
// if (!alreadyCallback) {
// callback(null, item + 200);
// return alreadyCallback = true;
// } else {
// // do nothing
// }
// }, 5000);
// } else {
if (!alreadyCallback) {
callback(null, item + 100);
return alreadyCallback = true;
} else {
// do nothing
}
// }
}, function (error, results) {
if (error) {
return console.log(error);
}
console.log(results);
});
程序员的常规思路,当遇到需要重复的繁杂代码时一定要想办法精简。
'use strict';
const async = require('async');
const list = [1, 2, 3, 4, 5, 6];
async.mapLimit(list, 10, function (item, callback) {
let alreadyCallback = false;
const _callback = function (error, result) {
if(!alreadyCallback) {
callback(error, result);
alreadyCallback = true
}
};
setTimeout(function () {
return _callback(new Error('manual set error'));
}, 3000);
// // 超时任务
// if (item === 3) {
// setTimeout(function () {
// return _callback(null, item + 200);
// }, 5000);
// } else {
return _callback(null, item + 100);
// }
}, function (error, results) {
if (error) {
return console.log(error);
}
console.log(results);
});
至于在有任务超时时是触发错误,还是忽略错误,返回一个标识的结果到结果集合中,然后再从结果集合中过滤掉超时标识,这个倒是可以根据需求自己修改代码了。