没有。我们还不能这样做。
ES6 Promise 还不支持取消。它正在路上,它的设计是很多人努力工作的。 声音 取消语义很难正确处理,这项工作正在进行中。关于“fetch” repo、esdiscuss 和 GH 上的其他几个 repo 有一些有趣的辩论,但如果我是你,我会耐心等待。
但是,但是,但是..取消真的很重要!
事实上,取消是真的客户端编程中的一个重要场景。您描述的中止 Web 请求等情况很重要,而且无处不在。
所以...语言把我搞砸了!
是的,很抱歉。 Promise 必须先进入,然后才能指定更多的东西——所以它们没有像 .finally 和 .cancel 这样的有用的东西就进入了——尽管它正在通过 DOM 达到规范的过程中。取消不是事后的想法,它只是时间限制和 API 设计的一种更迭代的方法。
那我该怎么办?
您有多种选择:
- 使用像 bluebird 这样的第三方库,它的移动速度比规范快得多,因此可以取消以及其他许多好处 - 这就是 WhatsApp 等大公司所做的。
- 传递一个取消令牌。
使用第三方库非常明显。至于令牌,你可以让你的方法接受一个函数,然后调用它,如下所示:
function getWithCancel(url, token) { // the token is for cancellation
var xhr = new XMLHttpRequest;
xhr.open("GET", url);
return new Promise(function(resolve, reject) {
xhr.onload = function() { resolve(xhr.responseText); });
token.cancel = function() { // SPECIFY CANCELLATION
xhr.abort(); // abort request
reject(new Error("Cancelled")); // reject the promise
};
xhr.onerror = reject;
});
};
这会让你做什么:
var token = {};
var promise = getWithCancel("/someUrl", token);
// later we want to abort the promise:
token.cancel();
您的实际用例 - last
使用令牌方法并不太难:
function last(fn) {
var lastToken = { cancel: function(){} }; // start with no op
return function() {
lastToken.cancel();
var args = Array.prototype.slice.call(arguments);
args.push(lastToken);
return fn.apply(this, args);
};
}
这会让你做什么:
var synced = last(getWithCancel);
synced("/url1?q=a"); // this will get canceled
synced("/url1?q=ab"); // this will get canceled too
synced("/url1?q=abc"); // this will get canceled too
synced("/url1?q=abcd").then(function() {
// only this will run
});
不,像 Bacon 和 Rx 这样的库在这里不会“发光”,因为它们是可观察的库,它们只是具有与用户级承诺库相同的优势,即不受规范约束。我想我们会等待在 ES2016 中看到 observables 原生化。不过,它们 很适合预先输入。