ES6 await强制停止的方法
ES6提供了async/await的语法,但是我实际工作过程中遇到了一些问题,await无法强制关闭,我无法写一个线程(setTimeout)来监视await的运行状况。如果在规定时间内没有操作完成,则强制关闭await。PS:思路是通过网上的例子改进而来。
核心代码:
const makeCancelable =(promise) => {
let hasCanceled_ = false;
let a={},b={};
const wrappedPromise = new Promise((resolve, reject) => {
promise.then((val) =>
//如果Promise执行完成,判断状态是否正常返回
hasCanceled_ ? null : resolve(val)
);
promise.catch((error) =>
hasCanceled_ ? null : reject(error)
);
a=resolve;//将完成函数赋值给a
b=reject;
});
return {
promise: wrappedPromise,
cancel() {
a({isCanceled: true});
hasCanceled_ = true;
},
async start(timeout){
if(typeof timeout=="number" && timeout>0){
let host=this;
setTimeout(function(){
host.cancel();
},timeout)
}
return await wrappedPromise;
}
};
};
使用完整示例
function timeout(delay) {
console.log("延时:"+delay+"ms");
return new Promise((resolve, reject) => {
setTimeout(() => {
try {
resolve(1)
} catch (e) {
reject(0)
}
}, delay)
})
}
const makeCancelable =(promise) => {
let hasCanceled_ = false;
let a={},b={};
const wrappedPromise = new Promise((resolve, reject) => {
promise.then((val) =>
//如果Promise执行完成,判断状态是否正常返回
hasCanceled_ ? null : resolve(val)
);
promise.catch((error) =>
hasCanceled_ ? null : reject(error)
);
a=resolve;//将完成函数赋值给a
b=reject;
});
return {
promise: wrappedPromise,
cancel() {
a({isCanceled: true});
hasCanceled_ = true;
},
async start(timeout){
if(typeof timeout=="number" && timeout>0){
let host=this;
setTimeout(function(){
host.cancel();
},timeout)
}
return await wrappedPromise;
}
};
};
(async () => {
console.log("开始");
console.log("测试1");
let ss=makeCancelable(timeout(30*1000));
let s1=await ss.start(10*1000);//两种使用方法,1为设置超时时间
console.log(s1);
if(s1.isCanceled){
console.log("await被强制关闭");
}
console.log("测试2");
let ss=makeCancelable(timeout(30*1000));
setTimeout(function(){
ss.cancel();//两种使用方法,2为使用cancel方法强制关闭
},10*1000);
let s1=await ss.start();
console.log(s1);
if(s1.isCanceled){
console.log("await被强制关闭");
}
console.log("结束")
})();
8 回复
– 内置语法 Promise.race 了解下?
- 阮老师:http://es6.ruanyifeng.com/#docs/promise#Promise-race
- 相关类库: https://github.com/sindresorhus/promise-fun 里面的
p-timeout
const pTimeout = require('p-timeout');
try {
const result = await pTimeout(longTask, 50);
} catch (error) {
// timeout error
}
原理很简单,手写如下:
async function run() {
const result = await Promise.race([
longTask(),
timeout(1000),
]);
console.log(result);
}
run().catch(console.error);
async function longTask() {
return new Promise((resolve) => {
setTimeout(() => {
resolve('long job is done!');
}, 2000);
});
}
async function timeout(ms) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error(`timeout ${ms}ms`));
}, ms);
});
}
@atian25 感谢
@atian25 详细看了一个race的用法,看来我的基础知识还是不够啊。非常感谢。
学习了!
但事实上,楼主所谓await强制停止并未实现,放到await中的代码没有因为另一个任务抛错终止。据我所知,直接取出micro task的方法不存在,只有间接的在异步代码写反复检测是否超时。
先抛开实现代码,思考一个问题,已经将数据请求从 socket 发出到网络中,是否还能阻碍这些数据继续传递下去呢?
Promise 中执行一些资源属性的异步操作时,停止 await 并不是仅仅将 promise 的状态置为 resovle 或者 reject,如何释放/停止已经开始执行的资源,也是一个难点
这正是 AbortSignal / Cancellation API 要考虑的事