Annuler la vanille, ECMAScript 6 Promesse de la chaîne d'

Est-il une méthode pour effacer le .thens de JavaScript Promise exemple?

J'ai écrit un script JavaScript framework de test sur le dessus de QUnit. Le cadre d'exécuter des tests de manière synchrone en cours d'exécution, chacune dans un Promise. (Désolé pour la longueur de ce bloc de code. J'ai commenté du mieux que je peux, de sorte qu'il se sent moins fastidieuse.)

/* Promise extension -- used for easily making an async step with a
timeout without the Promise knowing anything about the function 
it's waiting on */
$$.extend(Promise, {
asyncTimeout: function (timeToLive, errorMessage) {
var error = new Error(errorMessage || "Operation timed out.");
var res, //resolve()
rej, //reject()
t,   //timeout instance
rst, //reset timeout function
p,   //the promise instance
at;  //the returned asyncTimeout instance
function createTimeout(reject, tempTtl) {
return setTimeout(function () {
//triggers a timeout event on the asyncTimeout object so that,
//if we want, we can do stuff outside of a .catch() block
//(may not be needed?)
$$(at).trigger("timeout");
reject(error);
}, tempTtl || timeToLive);
}
p = new Promise(function (resolve, reject) {
if (timeToLive != -1) {
t = createTimeout(reject);
//reset function -- allows a one-time timeout different
//   from the one original specified
rst = function (tempTtl) {
clearTimeout(t);
t = createTimeout(reject, tempTtl);
}
} else {
//timeToLive = -1 -- allow this promise to run indefinitely
//used while debugging
t = 0;
rst = function () { return; };
}
res = function () {
clearTimeout(t);
resolve();
};
rej = reject;
});
return at = {
promise: p,
resolve: res,
reject: rej,
reset: rst,
timeout: t
};
}
});
/* framework module members... */
test: function (name, fn, options) {
var mod = this; //local reference to framework module since promises
//run code under the window object
var defaultOptions = {
//default max running time is 5 seconds
timeout: 5000
}
options = $$.extend({}, defaultOptions, options);
//remove timeout when debugging is enabled
options.timeout = mod.debugging ? -1 : options.timeout;
//call to QUnit.test()
test(name, function (assert) {
//tell QUnit this is an async test so it doesn't run other tests
//until done() is called
var done = assert.async();
return new Promise(function (resolve, reject) {
console.log("Beginning: " + name);
var at = Promise.asyncTimeout(options.timeout, "Test timed out.");
$$(at).one("timeout", function () {
//assert.fail() is just an extension I made that literally calls
//assert.ok(false, msg);
assert.fail("Test timed out");
});
//run test function
var result = fn.call(mod, assert, at.reset);
//if the test returns a Promise, resolve it before resolving the test promise
if (result && result.constructor === Promise) {
//catch unhandled errors thrown by the test so future tests will run
result.catch(function (error) {
var msg = "Unhandled error occurred."
if (error) {
msg = error.message + "\n" + error.stack;
}
assert.fail(msg);
}).then(function () {
//resolve the timeout Promise
at.resolve();
resolve();
});
} else {
//if test does not return a Promise, simply clear the timeout
//and resolve our test Promise
at.resolve();
resolve();
}
}).then(function () {
//tell QUnit that the test is over so that it can clean up and start the next test
done();
console.log("Ending: " + name);
});
});
}

Si un temps de test, mon délai d'attente Promesse assert.fail() sur le test, alors que le test est considérée comme un échec, ce qui est bien et bon, mais le test continue à s'exécuter parce que le test de la Promesse (result) est toujours en attente de le résoudre.

J'ai besoin d'un bon moyen d'annuler mon test. Je peux le faire par la création d'un champ dans le cadre du module this.cancelTest ou quelque chose, et en vérifiant de temps en temps (par exemple au début de chaque then() itération) dans le test qu'à s'annuler. Cependant, dans l'idéal, je pourrais utiliser $$(at).on("timeout", /* something here */) pour effacer le reste then()s sur mon result variable, de sorte que rien de tout le reste du test est exécuté.

Fait quelque chose comme ça existent?

Mise À Jour Rapide

J'ai essayé d'utiliser Promise.race([result, at.promise]). Il n'a pas de travail.

Mise à jour 2 + confusion

Pour débloquer moi, j'ai ajouté quelques lignes avec la mod.cancelTestet d'interrogation dans le test idée. (J'ai également supprimé l'événement déclencheur.)

return new Promise(function (resolve, reject) {
console.log("Beginning: " + name);
var at = Promise.asyncTimeout(options.timeout, "Test timed out.");
at.promise.catch(function () {
//end the test if it times out
mod.cancelTest = true;
assert.fail("Test timed out");
resolve();
});
//...
}).then(function () {
//tell QUnit that the test is over so that it can clean up and start the next test
done();
console.log("Ending: " + name);
});

J'ai mis un point d'arrêt dans le catch déclaration, et il est frappé. Ce qui est déroutant moi, c'est maintenant que le then() déclaration n'est pas appelé. Des idées?

Mise à jour 3

Pensé que le dernier truc. fn.call() a été de lancer une erreur que je n'ai pas de capture, de sorte que le test de la promesse était de rejet avant at.promise.catch() pourrait le résoudre.

  • Il est possible de faire une annulation ES6 promesses, mais il n'est pas une propriété de la promesse (plutôt - c'est une propriété de la fonction qui retourne) je peux faire un court exemple, si vous êtes intéressés.
  • Je sais, ça fait près d'un an, mais je suis toujours intéressé si vous avez le temps d'écrire un exemple. 🙂
  • Cela fait un an mais il a été officiellement discutée deux jours avant-hier avec des jetons d'annulation et de résiliation des promesses de déménagement à l'étape 1.
  • L'ES6 réponse à l'annulation d'une Promesse est Observable. Vous pouvez lire plus à ce sujet ici : github.com/Reactive-Extensions/RxJS
  • Reliant ma réponse sur l'utilisation de la Prex bibliothèque pour la promesse d'annulation.
InformationsquelleAutor dx_over_dt | 2015-04-06