Javascript 函数内部的闭包不是 "remember" 它的环境

Javascript closure inside function doesn't "remember" it's environment

我有一个函数,它从数据库中检索数据并将其传递给回调。出于优化目的,我希望此数据最多每 60 秒更新一次。我的闭包函数如下所示:

function delayedUpdate(fn, delay, callback) {
  var nextCall = Date.now();
  var data = false;

  (function () {
    if (nextCall <= Date.now()) {
      nextCall = Date.now() + delay;
      fn(function (err, res) {
        data = err ? false : res;
        callback(err, data);
      });
    } else {
      callback(null, data);
    }
  })();
}

我注意到当我 "construct" 这个经常被调用的函数在我想要的函数中时,我基本上是在循环中创建一个闭包,所以它没有机会正常工作:

function update()
{
  delayedUpdate(server.getDbData, 60000, function (err, data) {
    someDataToRender = data;
  });
}

在其他函数中包装 delayedUpdate 并分配给变量也不起作用。我怎样才能实现我的目标?我知道这可能是个愚蠢的问题,但我仍在学习。

你的代码没问题。您只需要在函数外声明变量 nextCalldata

var nextCall = Date.now();
var data = false;

function delayedUpdate(fn, delay, callback) {

    if (nextCall <= Date.now()) {

        nextCall = Date.now() + delay;

        fn(function (err, res) {
            data = err ? false : res;
            callback(err, data);
        });
    } else {
        callback(null, data);
    }
}

我想你想要的是你的原始代码:

function delayedUpdate(fn, delay, callback) {
  var nextCall = Date.now();
  var data = false;

  return function () {
    if (nextCall <= Date.now()) {
      nextCall = Date.now() + delay;
      fn(function (err, res) {
        data = err ? false : res;
        callback(err, data);
      });
    } else {
      callback(null, data);
    }
  };
}

那么您的 update 函数将是:

var update = delayedUpdate((server.getDbData, 60000, function (err, data) {
  someDataToRender = data;
});

update是调用delayedUpdate返回的函数。当您调用 update 时,它会进行时间戳检查。

需要注意的一件事:getDbData 函数可能不喜欢在没有 server 对象的上下文的情况下被调用,无论它是什么。如果是这样,则设置应如下所示:

var update = delayedUpdate((server.getDbData.bind(server), 60000, function (err, data) {
  someDataToRender = data;
});