【问题标题】:Cancelling promises取消承诺
【发布时间】:2014-08-28 19:38:37
【问题描述】:

用户可以通过在 UI 中输入值来进行异步调用。

当用户更改 UI 中的值时,会进行另一个异步调用 - 可能在提供给从异步调用返回的承诺的回调被调用之前。

正在使用的异步 API 返回一个基于 Q 的承诺。

如何优雅地取消原始调用,确保即使系统返回第一次调用的值,promise 的 .then 部分也不会使用该值调用(但最终会在第二个异步调用完成)?

【问题讨论】:

  • 我在返回的承诺原型上看不到拒绝。
  • promise 的使用者不能修改它 - 只有 deferred 可以修改。
  • 好吧,我有一个根本的误解。作为返回 Promise 的 API 的客户端,我可以取消调用提供给 Promise 的 then 方法的回调吗?
  • @Ben monkey 修补请求承诺或使用支持取消的库。
  • @Ben 也 - 是的,如果您使用支持它的库,您可以。

标签: javascript promise q cancellation


【解决方案1】:

以前我遇到过这样的案例(node.js),我要么在做 Web 请求,要么在做 db 请求。我有一个超时对象,我认为它是可以取消的(对不起,不记得细节)并且对它们都有承诺。因此,如果网页先返回,我会取消超时并返回 html。如果首先发生超时,我将一些 JSON 中的“超时”字段更新为“是”,这样如果网络调用返回,它就会知道死了。这有点令人兴奋,因为有了这些承诺,我可以进入函数一次,实际上返回两次!

希望有帮助

-汤姆

【讨论】:

    【解决方案2】:

    没有一些取消 API,每个异步调用都将运行到完成,但如果您正在寻找的只是取消 .then() 函数,那么这是可行的。最直接的方式是计数器:

    var counter = 0;
    
    function onClick() {
      counter++;
      doAsyncCall().then(function(result) {
        if (!--counter) {
          myFunc(result);
        }
      });
    }
    

    但你要求优雅,所以也许一个更可重用的构造是这样的:

    var idle;
    
    function onClick(){
      idle = Overtake(idle, doAsyncCall());
      idle.then(myFunc).then(myOtherFunc);
    }
    

    可以这样实现:

    function Overtaker(prior, callp) {
      if (prior) {
        prior.cancel();
      }
      var p;
      p = new Promise(function(resolve, reject) {
        callp.then(function(value)  { return p && resolve(value); },
                   function(reason) { return p && reject(reason); });
      });
      this.cancel = function() { p = null; }
      this.then = function(onFulfilled, onRejected) {
        return p.then(onFulfilled, onRejected);
      }
    }
    
    function Overtake(prior, p) {
      return new Overtaker(prior, p);
    }
    

    我正在使用 ES6 Promise,但 Q Promise 看起来很相似,所以希望这也适用。

    【讨论】:

      猜你喜欢
      • 2017-10-09
      • 2018-12-10
      • 1970-01-01
      • 2017-11-23
      • 2015-01-23
      • 2015-02-13
      • 2015-07-25
      • 2021-02-02
      相关资源
      最近更新 更多