不,我们还不能那样做。
ES6Promise不支持取消还没有。它正在路上,它的设计是很多人非常努力的工作。声音消除语义很难做到正确,这是正在进行中的工作。关于“获取”存储库、esdiscuss 和其他几个关于 GH 的存储库存在有趣的争论,但如果我是你,我会耐心等待。
但是,但是,但是……取消真的很重要!
事实是,取消确实是客户端编程中的一个重要场景。您描述的诸如中止 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 这样的库在这里不会“发光”,因为它们是可观察的库,它们只是具有与用户级Promise库相同的优势,不受规范约束。我想我们会等待并在 ES2016 中看到 observables 成为原生的时候。不过,它们非常适合提前输入。