Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs React Redux源函数,确保设置多个侦听器?;_Reactjs_Redux - Fatal编程技术网

Reactjs React Redux源函数,确保设置多个侦听器?;

Reactjs React Redux源函数,确保设置多个侦听器?;,reactjs,redux,Reactjs,Redux,如何理解函数ensureCanMutateNextListeners 这是个好问题。在此处致电@gaearon发布从 reduxsubscribe函数的示例实现 let subscriptions = []; const subscribe = function (fn) { if (typeof fn !== 'function') { throw Error('The provided listener must be a function'); }

如何理解函数ensureCanMutateNextListeners
这是个好问题。在此处致电@gaearon

发布从

redux
subscribe函数的示例实现

let subscriptions = [];
const subscribe = function (fn) {
    if (typeof fn !== 'function') {
        throw Error('The provided listener must be a function');
    }

    var subscribed = true;

    // This line is what we are interested in
    subscriptions.push(fn);

    return function () {
        if (!subscribed) {
            return;
        }

        var index = subscriptions.indexOf(fn);
        subscriptions.splice(index, 1);
        subscribed = false;
    };
};
对于执行的每一次
发送
,我们必须通知每一位
订户

从博客

现在,您可能希望添加到subscribe函数中的一件事是对subscribers集合进行变异保持。您希望侦听器集合的原因不应在调度运行时更改

继续

因此,这里我们有一个函数ensureCanMutateNextListeners,当调用该函数时,检查两个数组是否是相同的数组引用,如果是,则使用slice克隆currentSubscriptions,以便在修改nextSubscriptions数组(添加或删除侦听器)时它不会影响任何当前正在运行的调度管道。这里的目标是确保调度所使用的侦听器是调度开始时的时间点


这个问题困扰了我很长一段时间,虽然上面的答案和博客文章提供了核心思想,但没有给出具体的例子

我的思考过程是:javaScript是单线程的,任何函数都有运行到完成的行为——所以说
subscribe
必须担心当前是否有分派操作在进行,这是没有意义的。如果我们在函数
subscribe
中,那么实际上也不可能在
dispatch
中:因为
subscribe
的主体中没有任何地方被直接或间接调用
dispatch

说到这里,我今天才意识到上述逻辑的一个缺陷,我想在这里分享一下。解释是,当在
订阅
中时,
调度
将不会运行,但反之则不正确<代码>订阅(和
取消订阅
)可能在
调度
中运行。这是
调度的来源

  function dispatch(action) {
    // ...

    const listeners = currentListeners = nextListeners
    for (let i = 0; i < listeners.length; i++) {
      const listener = listeners[i]
      listener()
    }

    return action
  }
现在,当我们发送时会发生什么?假设未使用
ensureCanMutateNextListeners
,并且
subscribe
实际将侦听器推送到
currentListeners

store.dispatch(action);
将在所有侦听器中循环:

for (let i = 0; i < listeners.length; i++) {
  const listener = listeners[i]
  listener()
}
但是,即使只使用
redux
公共api,也可能有其他情况会让某些
listener
以意外的方式改变侦听器数组


因此,
ensureCanMutateNextListeners
作为一种通用解决方案引入。在dispatch内部,任何对
subscribe
unsubscribe
的间接调用(只有两个公共函数
redux
允许您修改侦听器)都将变异
currentListeners的副本,从而产生更可预测的行为。在上面的例子中,通过使用
ensureCanMutateNextListeners
doSubscribe
将添加一个add-self到
监听器的副本中,调用时,
调度中的循环保持不受影响,并且没有任何问题。

今天挖掘redux文档,官方API文档对此做了一些解释:>订阅是在每次dispatch()调用之前进行快照的。如果在调用侦听器时订阅或取消订阅,这将不会对当前正在进行的dispatch()产生任何影响。但是,下一个dispatch()调用(无论是否嵌套)将使用订阅列表的最新快照。Aaron Powell在这里的博客文章:我实际上还有另一个问题:
for (let i = 0; i < listeners.length; i++) {
  const listener = listeners[i]
  listener()
}
const currentListenersCount = listeners.length;
for (let i = 0; i < currentListenersCount; i++) {
  const listener = listeners[i]
  listener()
}