承诺 - 是否可以强制取消承诺 [英] Promise - is it possible to force cancel a promise

查看:19
本文介绍了承诺 - 是否可以强制取消承诺的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 ES6 Promises 来管理我所有的网络数据检索,在某些情况下我需要强制取消它们.

I use ES6 Promises to manage all of my network data retrieval and there are some situations where I need to force cancel them.

基本上情况是这样的,我在 UI 上有一个预先输入的搜索,其中请求被委托给后端必须根据部分输入执行搜索.虽然这个网络请求 (#1) 可能需要一点时间,但用户继续输入最终会触发另一个后端调用 (#2)

Basically the scenario is such that I have a type-ahead search on the UI where the request is delegated to the backend has to carry out the search based on the partial input. While this network request (#1) may take a little bit of time, user continues to type which eventually triggers another backend call (#2)

这里#2 自然优先于#1,所以我想取消Promise 包装请求#1.我已经在数据层中缓存了所有 Promise,因此理论上我可以在尝试为 #2 提交 Promise 时检索它.

Here #2 naturally takes precedence over #1 so I would like to cancel the Promise wrapping request #1. I already have a cache of all Promises in the data layer so I can theoretically retrieve it as I am attempting to submit a Promise for #2.

但是,一旦我从缓存中检索它,我该如何取消 Promise #1?

But how do I cancel Promise #1 once I retrieve it from the cache?

有人可以建议一种方法吗?

Could anyone suggest an approach?

推荐答案

No.我们还不能这样做.

ES6 promise 尚不支持取消.它正在路上,它的设计是很多人非常努力的工作.声音取消语义很难正确处理,并且正在进行中.关于获取"存储库、esdiscuss 和其他几个关于 GH 的存储库存在有趣的争论,但如果我是你,我会耐心等待.

No. We can't do that yet.

ES6 promises do not support cancellation yet. It's on its way, and its design is something a lot of people worked really hard on. Sound cancellation semantics are hard to get right and this is work in progress. There are interesting debates on the "fetch" repo, on esdiscuss and on several other repos on GH but I'd just be patient if I were you.

事实上,取消在客户端编程中确实是一个重要的场景.您描述的诸如中止 Web 请求之类的情况很重要,而且无处不在.

It is, the reality of the matter is cancellation is really an important scenario in client-side programming. The cases you describe like aborting web requests are important and they're everywhere.

是的,很抱歉.在指定进一步的事情之前,承诺必须首先进入 - 所以他们在没有一些有用的东西的情况下进入,比如 .finally.cancel - 不过,它正在按照规范进行通过 DOM.取消是不是事后的想法,它只是时间限制和 API 设计的一种更具迭代性的方法.

Yeah, sorry about that. Promises had to get in first before further things were specified - so they went in without some useful stuff like .finally and .cancel - it's on its way though, to the spec through the DOM. Cancellation is not an afterthought it's just a time constraint and a more iterative approach to API design.

您有多种选择:

  • 使用像 bluebird 这样的第三方库,它的移动速度比规范快得多,因此可以取消以及一堆其他好东西 - 这就是像 WhatsApp 这样的大公司所做的.
  • 传递取消令牌.
  • Use a third party library like bluebird who can move a lot faster than the spec and thus have cancellation as well as a bunch of other goodies - this is what large companies like WhatsApp do.
  • Pass a cancellation token.

使用第三方库是很明显的.至于令牌,您可以让您的方法接收一个函数然后调用它,如下所示:

Using a third party library is pretty obvious. As for a token, you can make your method take a function in and then call it, as such:

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

使用令牌方法这并不太难:

Your actual use case - last

This isn't too hard with the token approach:

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 成为原生的时候.不过,它们很适合提前输入.

And no, libraries like Bacon and Rx don't "shine" here because they're observable libraries, they just have the same advantage user level promise libraries have by not being spec bound. I guess we'll wait to have and see in ES2016 when observables go native. They are nifty for typeahead though.

这篇关于承诺 - 是否可以强制取消承诺的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆