承诺 – 是否有可能强制取消承诺

我使用ES6承诺来pipe理我所有的networking数据检索,并且在某些情况下我需要强制取消它们。

基本上这种情况是这样的,我有一个提前input的search请求被委托给后端的用户界面必须执行基于部分input的search。 虽然这个networking请求(#1)可能需要一点时间,但是用户继续键入,最终触发另一个后端呼叫(#2)

这里#2自然优先于#1,所以我想取消承诺包装请求#1。 我已经有了数据层中所有Promise的caching,所以理论上我可以检索它,因为我试图提交#2的Promise。

但是,如果我从caching中检索到Promise#1,我该如何取消呢?

任何人都可以提出一个办法

不,我们还不能这样做。

ES6承诺不支持取消。 它正在发展,它的devise是很多人真正努力工作的。 声音消除语义很难得到正确的,这是正在进行的工作。 关于“取回”回购,关于生长激素的几个其他回购,还有一些有趣的争论,但如果我是你,我只是耐心等待。

但是,但是,取消是非常重要的!

事实上,取消在客户端编程中确实是一个重要的场景。 您所描述的情况就像中止Web请求一样重要,而且无处不在。

所以…语言搞砸了我!

对,对不起。 承诺必须在进一步的事情被指定之前先进入 – 所以他们进入没有一些有用的东西,如.finally.cancel – 它的方式,虽然,通过DOM的规范。 取消不是一个事后的想法,它只是一个时间约束和更复杂的APIdevise方法。

那我能做什么?

你有几个select:

  • 使用像蓝鸟这样的第三方库,可以比规范更快地移动,从而取消以及其他一些好东西 – 这就是像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的观测结果出现。 虽然他们漂亮。

标准的可撤销承诺build议失败了。

承诺不是履行它的asynchronous行为的控制面。 所有者与消费者混淆。 相反,创build可以通过一些传入令牌取消的asynchronous函数

另一个承诺是一个很好的标记,使取消易于与Promise.race实现:

示例:使用Promise.race取消前一个链的效果:

 let cancel = () => {}; input.oninput = function(ev) { let term = ev.target.value; console.log(`searching for "${term}"`); cancel(); let p = new Promise(resolve => cancel = resolve); Promise.race([p, getSearchResults(term)]).then(results => { if (results) { console.log(`results for "${term}"`,results); } }); } function getSearchResults(term) { return new Promise(resolve => { let timeout = 100 + Math.floor(Math.random() * 1900); setTimeout(() => resolve([term.toLowerCase(), term.toUpperCase()]), timeout); }); } 
 Search: <input id="input"> 

我已经检查了Mozilla的JS参考,并发现这一点:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/race

让我们来看看:

 var p1 = new Promise(function(resolve, reject) { setTimeout(resolve, 500, "one"); }); var p2 = new Promise(function(resolve, reject) { setTimeout(resolve, 100, "two"); }); Promise.race([p1, p2]).then(function(value) { console.log(value); // "two" // Both resolve, but p2 is faster }); 

我们在这里有p1,p2把Promise.race(...)作为参数,这实际上是创build新的parsing诺言,这就是你所要求的。