如何从AngularJS的$q.defer() Promise对象中移除回调函数

4

Angularjs中$q.defer()的promise对象接收notify回调函数,当我们提供多个时,它会保存并通知所有这些回调函数,即不会覆盖掉先前的。

var def=$q.defer();
def.promise.then(null, null, callback1);
def.promise.then(null, null, callback2);

如果我想要移除(注销)例如callback2,我该怎么做?

这里有一个实时的例子:

jsfiddle


不确定您是否可以,但是在回调函数内添加一个“if”条件语句,以检查您想要“注销”的情况如何? - Itamar L.
@ItamarL,那不是一个干净的解决方案。 - Mert Mertce
根据你描述问题的方式,似乎你真正想要的是事件总线或函数响应式编程,而不是 Promise。Promise 用于链接一系列异步调用。如果你正在寻找通知器、接收器,那么你需要的是事件总线。可以尝试使用 https://github.com/Gozala/events 或者 http://reactivex.io/,我认为你会非常喜欢 ReactiveX。 - initialxy
AngularJS已经有$emit和$broadcast机制。请注意,我不要求替代方案。问题就是它所问的,是否有一种方法。 - Mert Mertce
不,没有支持的方法来完成你所要求的。你的使用情况是什么?你想做什么? - dherman
2个回答

1

快速查看$q的来源,我们可以发现:

then: function(onFulfilled, onRejected, progressBack) {
  var result = new Deferred();

  this.$$state.pending = this.$$state.pending || [];
  this.$$state.pending.push([result, onFulfilled, onRejected, progressBack]);
  if (this.$$state.status > 0) scheduleProcessQueue(this.$$state);

  return result.promise;
}

因此,在$$state.pending堆栈中没有特定的标识符可以指向您的匿名回调函数,以便将其拼接出来。

我个人之前没有尝试过这个方法,但是如果您想要清除待处理堆栈,也许def.$$state.pending = [];就可以解决问题。然后,您只需重新分配您想要的def.then()回调即可。


是的,但只有当def.$$state没有任何其他跟踪时才可以这样做。我看到了很多处于等待状态的兄弟节点。这似乎很危险,但在仅需要保留一个回调函数时可以尝试。 - Mert Mertce
唯一直接访问state.pending的地方是在processQueue()中 - 在那里它有一个故障保护for (var i = 0, ii = pending.length; i < ii; ++i),其中长度将为0。 - pierdevara
所以看起来没有一个“官方”的方法来做到这一点,这使得你所写的成为了这个问题的答案。 - Mert Mertce

1

承诺被用来执行一系列异步进程。一旦设置了这个序列的一步,就无法(至少不是以优雅的方式)取消它。

如果我错了,请纠正我,但这正是你在这里尝试做的:你使用回调函数2设置一个步骤,然后尝试删除该步骤。相反,我建议仅在满足某些条件时设置回调函数2,例如:

var notifCallback;
if (true) {
    notifCallback = function(notif) {
        console.log('notify 1', notif);
    };
} else {
    notifCallback = function(notif) {
        console.log('notify 2', notif);
    };
}

def.promise.then(null, null, notifCallback);

在 jsFiddle 上的示例


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接