使用 async 发起多个耗时任务,超过规定时间后,能否取消正在进行的任务,进入结果处理回调。
发布于 8 年前 作者 W-v-W 5520 次预览 最后一次回复是 8 年前 来自 问答
代码如下 :
async.mapLimit(items, 10, function(item, callback){
taskStart(item, function(err, data){ // 发起耗时任务
if(err){
callback();
}else{
callback(null, data);
}
});
}, function(err, resul){
result = result.filter(n => n);
// ...
});
**问题 : ** 有没有简单的办法,设置任务时间上限,超时后直接进入结果处理。
7 回复
本楼正解
Promise.race() Promise.race方法同样是将多个Promise实例,包装成一个新的Promise实例。
var p = Promise.race([p1, p2, p3]); 上面代码中,只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。
Promise.race方法的参数与Promise.all方法一样,如果不是 Promise 实例,就会先调用下面讲到的Promise.resolve方法,将参数转为 Promise 实例,再进一步处理。
下面是一个例子,如果指定时间内没有获得结果,就将Promise的状态变为reject,否则变为resolve。
上面代码中,如果5秒之内fetch方法无法返回结果,变量p的状态就会变为rejected,从而触发catch方法指定的回调函数。
可以, 使用 promise.timeout https://cnodejs.org/topic/574f88811176fe255bb8d7e3
支持资源清理, 像发起一个 http 请求, 在 onCancel 里写上
req.abort之后, 如果不手动 abort, 请求还是会继续 本质上就是 Promise.race, 但是多了资源清理下载文件示例见 https://github.com/magicdawn/yun-playlist-downloader/blob/v0.11.0/lib/index.js#L132-L135 fn(arg1, arg2, onCancel) -> Promise 使用
fn_withtimeout = ptimeout(fn, timeout, true)最后一个 true 标识会在 fn 执行的时候传一个 onCancel@zengming00 合成的 Promise 如何设置并发数?
@zengming00 学习了 mark~,之前一直不知道promise.race 干毛用 = =
@zengming00 不知道你的“本楼正解”是自己写的还是楼主改的,感觉你的思路与楼主的示例代码有些不符。楼主示例代码给人的感觉是要运行一系列任务,如果所有都在规定时间内完成了,结果是这一系列任务结果的一个集合;如果其中有任务超时了,到达查实时间后不会卡住也会返回结果,结果为其中已经执行好的任务结果的一个集合。而你给出的 Promise.race 的解决方案,只要有一个任务成功执行就会 resolve,这样结果中不会包含其他任务的执行结果;在所有任务都执行超时时才会触发附加的超时的 reject。
以下是我的一个思路,如果理解不对也请谅解。
根据自己最冲动最初始的想法写代码,可以满足要求,但是略显繁杂,在所有需要 callback 的地方都需要判断。
程序员的常规思路,当遇到需要重复的繁杂代码时一定要想办法精简。
至于在有任务超时时是触发错误,还是忽略错误,返回一个标识的结果到结果集合中,然后再从结果集合中过滤掉超时标识,这个倒是可以根据需求自己修改代码了。
@DuanPengfei 先感谢@DuanPengfei 的启发。 我尝试过:
callback().var wrapped = async.timeout(foo, 3000);然后使用async.mapLimit(items, 10, wrapped ...);@W-v-W 恩恩,我没有考虑到每次并发耗时累计起来的总时间问题,最终代码这样的实现就能达到需求了 😊