【问题标题】:When will .bind() run?.bind() 什么时候运行?
【发布时间】:2018-06-06 20:01:27
【问题描述】:

我正在尝试使用更改的配置数据作为输入来安排一堆任务按时间间隔运行:

let configData = initConfig();  // Initialize configuration data from file

setInterval(taskA.bind(null, configData), TASK_A_WAIT);  // Task using config data

setInterval(taskB.bind(null, configData), TASK_B_WAIT);  // Task using config data

setInterval(taskC.bind(null, configData), TASK_C_WAIT);  // Task using config data

setInterval(refreshConfig.bind(null, (error, result) => {    // Update config data
    if (error) handleError(error);
    else configData = result;
}), CONFIG_REFRESH_WAIT);

目标是使用最后一个setInterval() 定期更新配置数据,以便前三个setInterval() 始终使用最新数据。但它会起作用吗?

在 javascript 的语义中,上面是否真的会每隔一段时间重新将函数绑定到最新的configData 对象?在这种情况下什么时候发生绑定?

【问题讨论】:

  • 否,因为configData = result 覆盖引用,而不是值。任务仍将绑定到旧引用。
  • @PatrickRoberts 因此,如果我理解正确,绑定将发生一次,但因为绑定是通过引用进行的,并且适当引用处的值随着最后一次 setInterval() 刷新配置数据的每次传递而更新,输入三个任务的configData 的值确实会在每个时间间隔内都是最新的?
  • 绑定是按值...排序的。问题是您的 configData 的引用正在更改,但 .bind() 将保留旧的引用。
  • @PatrickRoberts 所以如果configData 是一个对象,因为引用会改变,所以它不会工作。但是如果configData 不是对象,它会起作用吗?介意写一个答案,这样我就可以投票了吗?
  • configData 是什么无关紧要,它不会起作用。

标签: javascript node.js callback


【解决方案1】:

由于bind() 没有被包装在另一个函数中,所以它是就地同步执行的。

任务函数绑定到原始configData。如果用configData = result 重新分配,这不会影响绑定函数。

任务函数应该用函数包装以重新分配configData

setInterval(() => { taskA(configData) }, TASK_A_WAIT)

另一个适用于bind 的选项是为configData 对象保留相同的引用,这仅在初始configData 是一个对象时才有效:

setInterval(refreshConfig.bind(null, (error, result) => {
  ... 
  Object.assign(configData, result);
}), CONFIG_REFRESH_WAIT);

如果configData 有可能已经有可能不会被覆盖的属性,那么它应该首先是cleared

【讨论】:

    【解决方案2】:

    如果您希望任务继续引用configData 的实时版本,您应该像这样将匿名包装函数传递给setInterval() 的每个调用,它限定符号变量引用的范围,而不是绑定原始的每个函数的对象引用:

    let configData = initConfig();  // Initialize configuration data from file
    
    setInterval(() => taskA(configData), TASK_A_WAIT);  // Task using config data
    
    setInterval(() => taskB(configData), TASK_B_WAIT);  // Task using config data
    
    setInterval(() => taskC(configData), TASK_C_WAIT);  // Task using config data
    
    setInterval(refreshConfig.bind(null, (error, result) => {    // Update config data
        if (error) handleError(error);
        else configData = result;
    }), CONFIG_REFRESH_WAIT);
    

    或者,如果您不希望更改引用,并且您知道配置的结构永远不会改变,您可能更愿意将configData 设为const 引用并使用Object.assign() 进行浅拷贝result 的键,用 result 中的新值覆盖 configData 中的每个键:

    const configData = initConfig();  // Initialize configuration data from file
    
    setInterval(taskA.bind(null, configData), TASK_A_WAIT);  // Task using config data
    
    setInterval(taskB.bind(null, configData), TASK_B_WAIT);  // Task using config data
    
    setInterval(taskC.bind(null, configData), TASK_C_WAIT);  // Task using config data
    
    setInterval(refreshConfig.bind(null, (error, result) => {    // Update config data
        if (error) handleError(error);
        else Object.assign(configData, result);
    }), CONFIG_REFRESH_WAIT);
    

    【讨论】:

    • 哈。没有看上面以确保其他人也没有做同样的事情。难怪,没有那么多选择可以工作。
    • 实际上这里有一些我不知道的关于 javascript 的非常有趣的东西。 const 关键字可用于进行常量引用,具有可变值?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-18
    • 1970-01-01
    • 2016-09-17
    相关资源
    最近更新 更多