Annuler la fonction asynchrome ecmascript7

Existe-t-il un moyen d'annuler une fonction asynchrome ES7?

Dans cet exemple, en cliquant sur, je souhaite interrompre l'appel de fonction asynchique avant d'appeler un nouveau.

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(); }); 

Il n'y a rien intégré à JavaScript, mais vous pouvez facilement lancer votre propre.

MS.Net utilise le concept d'un jeton d'annulation pour l'annulation de Tâches (l'équivalent .net de Promises). Cela fonctionne très bien, alors voici une version réduite pour JavaScript.

Dites que vous avez fait une classe conçue pour représenter l'annulation:

 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); } } 

Alors vous avez mis à jour votre fonction de sommeil pour être au courant de ce jeton:

 function delayAsync(timeMs, cancellationToken){ return new Promise((resolve, reject) => { setTimeout(resolve, timeMs); if(cancellationToken) { cancellationToken.register(reject); } }); } 

Maintenant, vous pouvez utiliser le jeton pour annuler la fonction asynchmène sur laquelle il a été transmis:

 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

… ou faites plus ou moins la même chose en utilisant un style async / await à la place:

 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) 

À moins que votre question soit purement théorique, je suppose que vous utilisez Babel, Type ou un autre transpiler pour le support es6-7 et probablement un polyfill pour des promesses dans des environnements existants. Bien qu'il soit difficile de dire ce qui deviendra standard dans le futur, il existe un moyen non standard d'obtenir ce que vous voulez aujourd'hui:

  1. Utilisez le type de fichier pour obtenir les fonctionnalités es6 et async / await.
  2. Utilisez Bluebird pour des promesses dans tous les environnements pour obtenir un soutien d'annulation prometteur.
  3. Utilisez l' annulable annulable qui rend les annulations de Bluebird lentes avec Async / Wait in dans le type.