Não. Não podemos fazer isso ainda.
ES6 promessas não suportam o cancelamento ainda . Está a caminho, e seu design é algo em que muitas pessoas trabalharam muito. A semântica de cancelamento de som é difícil de acertar e isso é um trabalho em andamento. Existem debates interessantes sobre o repositório "fetch", no esdiscuss e em vários outros repositórios no GH, mas eu seria paciente se fosse você.
Mas, mas, mas .. o cancelamento é muito importante!
É, a realidade da questão é que o cancelamento é realmente um cenário importante na programação do lado do cliente. Os casos que você descreve, como abortar solicitações da web, são importantes e estão em toda parte.
Então ... a linguagem me ferrou!
Sim, desculpe por isso. As promessas tinham que ser feitas antes que outras coisas fossem especificadas - então elas entraram sem algumas coisas úteis como .finally
e .cancel
- está a caminho, porém, para a especificação por meio do DOM. O cancelamento não é uma reflexão tardia, é apenas uma restrição de tempo e uma abordagem mais iterativa para o design da API.
Então o que eu posso fazer?
Você tem várias alternativas:
- Use uma biblioteca de terceiros como o bluebird, que pode se mover muito mais rápido do que a especificação e, portanto, tem cancelamento, bem como um monte de outras vantagens - é isso que grandes empresas como o WhatsApp fazem.
- Passe um token de cancelamento .
Usar uma biblioteca de terceiros é bastante óbvio. Quanto a um token, você pode fazer seu método assumir uma função e chamá-la, como tal:
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;
});
};
O que o deixaria fazer:
var token = {};
var promise = getWithCancel("/someUrl", token);
token.cancel();
Seu caso de uso real - last
Isso não é muito difícil com a abordagem de 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);
};
}
O que o deixaria fazer:
var synced = last(getWithCancel);
synced("/url1?q=a");
synced("/url1?q=ab");
synced("/url1?q=abc");
synced("/url1?q=abcd").then(function() {
});
E não, bibliotecas como Bacon e Rx não "brilham" aqui porque são bibliotecas observáveis, elas apenas têm a mesma vantagem que bibliotecas de promessa em nível de usuário têm por não serem vinculadas às especificações. Acho que vamos esperar para ver no ES2016 quando os observáveis se tornarem nativos. Eles são bacanas para digitação antecipada.