有没有办法取消ES7异步功能?
在这个例子中,点击后,我想在调用new之前中止异步函数调用。
async function draw(){
for(;;){
drawRandomRectOnCanvas();
await sleep(100);
}
}
function sleep(t){
return new Promise(cb=>setTimeout(cb,t));
}
let asyncCall;
window.addEventListener('click', function(){
if(asyncCall)
asyncCall.abort(); // this dont works
clearCanvas();
asyncCall = draw();
});
答案 0 :(得分:5)
JavaScript还没有内置任何内容,但您可以轻松推出自己的内容。
MS.Net使用取消令牌的概念来取消任务(.net相当于Promises)。它工作得非常好,所以这里是JavaScript的缩减版。
假设您创建了一个旨在表示取消的课程:
function CancellationToken(parentToken){
if(!(this instanceof CancellationToken)){
return new CancellationToken(parentToken)
}
this.isCancellationRequested = false;
var cancellationPromise = new Promise(resolve => {
this.cancel = e => {
this.isCancellationReqested = true;
if(e){
resolve(e);
}
else
{
var err = new Error("cancelled");
err.cancelled = true;
resolve(err);
}
};
});
this.register = (callback) => {
cancellationPromise.then(callback);
}
this.createDependentToken = () => new CancellationToken(this);
if(parentToken && parentToken instanceof CancellationToken){
parentToken.register(this.cancel);
}
}
然后你更新了睡眠功能以了解这个标记:
function delayAsync(timeMs, cancellationToken){
return new Promise((resolve, reject) => {
setTimeout(resolve, timeMs);
if(cancellationToken)
{
cancellationToken.register(reject);
}
});
}
现在您可以使用令牌取消传递给它的异步函数:
var ct = new CancellationToken();
delayAsync(1000)
.then(ct.cancel);
delayAsync(2000, ct)
.then(() => console.log("ok"))
.catch(e => console.log(e.cancelled ? "cancelled" : "some other err"));
http://codepen.io/spender/pen/vNxEBZ
...或者使用async / await样式或多或少做同样的事情:
async function Go(cancellationToken)
{
try{
await delayAsync(2000, cancellationToken)
console.log("ok")
}catch(e){
console.log(e.cancelled ? "cancelled" : "some other err")
}
}
var ct = new CancellationToken();
delayAsync(1000).then(ct.cancel);
Go(ct)
答案 1 :(得分:3)
除非您的问题纯粹是理论上的,否则我假设您使用Babel,Typescript或其他一些转换器来支持es6-7,并且可能会在遗留环境中使用一些polyfill来实现承诺。虽然很难说将来会成为什么样的标准,但是有一种非标准的方式来获得你想要的东西: