【问题标题】:Cancel a callback in javascript在javascript中取消回调
【发布时间】:2015-04-02 00:38:56
【问题描述】:

我有类似的东西:

function MyObject() {
  var self = this;

  this.callback = function() {
    self.finishParams = Array.prototype.slice.call(arguments);
    self.parent.finish();
  }

  this.start = function() {
    this.currentCallback = this.callback
    this.startFunc.apply(this.startFunc, this.startParams.concat(this.currentCallback));
  }
}

this.startFunc 是一个类似于 function(param1, param2, param3, callback) 的函数 我无法控制 this.startFunc,只是它会调用带有一些参数的回调。

问题

我有一个 this.currentCallback,因为我需要能够取消回调。也就是我已经调用了this.startFunc,需要防止回调。

问题是,MyObject 可能会发送另一个回调(一次从不发送 2 个),但如果我在需要时不立即取消第一个,当我取回它们时我不知道哪个是有效的!可能会令人困惑,所以这里有一个图表:

  • 发送回调 1 关闭
  • 需要取消!在这里以某种方式取消回调 A
  • 发送回调 2 关闭(仍然说函数有回调 1)

此时,如果我没有取消 A,那么当我收到回调时,我将不知道它是哪个。如果我确实取消了 A,那么我知道是 B,没有人担心。

如果你不明白请告诉我:)

【问题讨论】:

  • 我认为你的做法是错误的......而不是取消当前的回调......你需要取消正在调用回调的进程......
  • 也许您正在寻找去抖动? stackoverflow.com/q/15927371/218196
  • @ArunPJohny startFunc 中可能还有其他无法取消的内容。如果你说你可以取消只调用回调的进程,我该怎么做,我怎么知道要取消哪个?
  • 回调只是一个函数。由您提供回调的函数来决定是否以及何时调用它。没有通用的 API 可以用来控制它,它是特定于应用程序的。
  • 如果不能影响startFunc...可以控制回调的参数吗?参数中是否有任何独特的东西,或者您可以在其中存储独特的东西?

标签: javascript function callback


【解决方案1】:

在 cmets 中提出的方案的概念验证:为每个回调创建一个新的闭包,让回调识别它是否处于活动状态。

function foreignAPIThatStartsACallback(callback) {
  setTimeout(callback, 1000);
}

var activeCallback;

function wrapCallback(callback) {
  var args = Array.prototype.slice.call(arguments, 1);
  var that = this;
  var wrappedCallback = function() {
    if (wrappedCallback == activeCallback) {
      callback.apply(that, args);
    }
  }
  activeCallback = wrappedCallback;
  return wrappedCallback;
}

function myCallback(what, who) {
  console.log(who + " says " + what);
}

foreignAPIThatStartsACallback(wrapCallback(myCallback, "Hello", "Mario"));
foreignAPIThatStartsACallback(wrapCallback(myCallback, "Goodbye", "Luigi"));
// Mario is cancelled when Luigi gets started

有多个可能的活动:

function foreignAPIThatStartsACallback(callback) {
  setTimeout(callback, 1000);
}

var activeCallbacks = {};

function wrapCallback(callback) {
  if (!wrapCallback.count) wrapCallback.count = 0;
  wrapCallback.count++;
  var args = Array.prototype.slice.call(arguments, 1);
  var that = this;
  var wrappedCallback = function() {
    if (wrappedCallback.id in activeCallbacks) {
      cancelCallback(wrappedCallback);
      callback.apply(that, args);
    }
  }
  wrappedCallback.id = wrapCallback.count;
  activeCallbacks[wrapCallback.count] = true;
  return wrappedCallback;
}

function cancelCallback(wrappedCallback) {
  delete activeCallbacks[wrappedCallback.id];
}

function myCallback(what, who) {
  console.log(who + " says " + what);
}


var marioCallback = wrapCallback(myCallback, "Hello", "Mario");
foreignAPIThatStartsACallback(marioCallback);
var luigiCallback = wrapCallback(myCallback, "Goodbye", "Luigi");
foreignAPIThatStartsACallback(luigiCallback);
var daisyCallback = wrapCallback(myCallback, "Mama?", "Peach");
foreignAPIThatStartsACallback(daisyCallback);

cancelCallback(luigiCallback);
// Mario and Daisy go off

【讨论】:

  • so WrappedCallback 将自己与 activeCallback 进行比较?
  • 是的。由于每个回调都是单独创建的,因此简单的对象标识就足够了。但是,这只是一个示例,还有更多方法可以做到这一点。关键是,如果你不能影响回调,回调负责知道它是否应该处理。此包装器可自动执行该过程,但您也可以采用更符合您需求的不太通用的方式来实现。
猜你喜欢
  • 2021-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-19
  • 2013-02-08
  • 1970-01-01
  • 1970-01-01
  • 2017-11-04
相关资源
最近更新 更多