No. Non possiamo ancora farlo.
Le promesse di ES6 non supportano ancora la cancellazione . Sta arrivando e il suo design è qualcosa su cui molte persone hanno lavorato molto duramente. La semantica della cancellazione del suono è difficile da ottenere correttamente e questo è un lavoro in corso. Ci sono dibattiti interessanti sul repo "fetch", su discus e su molti altri repo su GH, ma sarei solo paziente se fossi in te.
Ma, ma, ma .. la cancellazione è davvero importante!
La realtà della questione è che la cancellazione è davvero uno scenario importante nella programmazione lato client. I casi che descrivi come richieste web interrotte sono importanti e sono ovunque.
Quindi ... la lingua mi ha fregato!
Sì, mi dispiace per quello. Le promesse dovevano arrivare prima che venissero specificate ulteriori cose - quindi sono entrate senza alcune cose utili come .finally
e .cancel
- è in arrivo, però, alle specifiche attraverso il DOM. L'annullamento non è un ripensamento, è solo un vincolo di tempo e un approccio più iterativo alla progettazione delle API.
Quindi cosa posso fare?
Hai diverse alternative:
- Usa una libreria di terze parti come bluebird che può muoversi molto più velocemente delle specifiche e quindi avere la cancellazione e un sacco di altre chicche: questo è ciò che fanno le grandi aziende come WhatsApp.
- Passa un token di annullamento .
L'uso di una libreria di terze parti è abbastanza ovvio. Per quanto riguarda un token, puoi fare in modo che il tuo metodo prenda una funzione e quindi la chiami, come tale:
function getWithCancel(url, token) {
var xhr = new XMLHttpRequest;
xhr.open("GET", url);
return new Promise(function(resolve, reject) {
xhr.onload = function() { resolve(xhr.responseText); });
token.cancel = function() {
xhr.abort();
reject(new Error("Cancelled"));
};
xhr.onerror = reject;
});
};
Che ti permetterebbe di fare:
var token = {};
var promise = getWithCancel("/someUrl", token);
token.cancel();
Il tuo caso d'uso effettivo - last
Questo non è troppo difficile con l'approccio token:
function last(fn) {
var lastToken = { cancel: function(){} };
return function() {
lastToken.cancel();
var args = Array.prototype.slice.call(arguments);
args.push(lastToken);
return fn.apply(this, args);
};
}
Che ti permetterebbe di fare:
var synced = last(getWithCancel);
synced("/url1?q=a");
synced("/url1?q=ab");
synced("/url1?q=abc");
synced("/url1?q=abcd").then(function() {
});
E no, biblioteche come Bacon e Rx non "brillano" qui perché sono librerie osservabili, hanno solo lo stesso vantaggio che le biblioteche promesse a livello utente hanno non essendo vincolate alle specifiche. Immagino che aspetteremo di avere e vedere in ES2016 quando gli osservabili diventeranno nativi. Tuttavia sono eleganti per i tipografi.