【问题标题】:How to get last value from throttled function如何从节流函数中获取最后一个值
【发布时间】:2016-04-18 15:21:31
【问题描述】:

_.throttle 函数的文档指出:

创建一个限制函数,每次最多只调用一次 func 每等待毫秒。节流功能带有取消 取消延迟函数调用的方法和刷新方法 立即调用它们。提供一个选项对象来指示是否 func 应该在等待的前沿和/或后沿调用 超时。使用提供给 节流功能。对节流函数的后续调用返回 最后一次 func 调用的结果

我对这条线感兴趣:

对受限制函数的后续调用返回 最后一次 func 调用的结果

我试过了:

var throttled = _.throttle(updateModelData, 1000);
service.on('change', function () {
    throttled(5);
});

function updateModelData(data) {
    // all calls here log 5's
    console.log(data);
    return data;
}

setTimeout(function() {
    throttled(); // here updateModelData is executed with `undefined` value
}, 5000);

问题是throttled() 触发函数而不返回数据。如何调用它以返回最后的数据?

编辑:

根据源码,只有在不存在挂起的函数调用时才会返回值isCalled === false

  function debounced() {
    args = arguments;
    stamp = now();
    thisArg = this;
    trailingCall = trailing && (timeoutId || !leading);

    if (maxWait === false) {
      var leadingCall = leading && !timeoutId;
    } else {
      if (!maxTimeoutId && !leading) {
        lastCalled = stamp;
      }
      var remaining = maxWait - (stamp - lastCalled),
          isCalled = remaining <= 0 || remaining > maxWait;

      !!!!! HERE
      if (isCalled) {
        if (maxTimeoutId) {
          maxTimeoutId = clearTimeout(maxTimeoutId);
        }
        lastCalled = stamp;
        result = func.apply(thisArg, args);
      }
      else if (!maxTimeoutId) {
        maxTimeoutId = setTimeout(maxDelayed, remaining);
      }
    }
    ...
    return result;
  }

所以以下将起作用:

var throttled = _.throttle(updateModelData, 10000);
service.on('change', function () {
    throttled(5);
});

function updateModelData(data) {
    // all calls here log 5's
    console.log(data);
    return data;
}

setTimeout(function() {
    throttled(); // returns 5
}, 15000);

【问题讨论】:

  • 什么是this.getData
  • @elclanrs,我已经从示例中删除了this.getData(),现在应该清楚了,请看一下
  • @Maximus 你把节流函数返回的值保存在哪里?
  • @Neal,我不知道,该值存储在 lodash 的 debounce 函数中。

标签: javascript lodash


【解决方案1】:

问题在于,当您有前导调用(_.throttle 的默认行为)时,当您第一次调用节流函数(或在延迟时间过后第一次调用它)时,它会立即调用底层函数,在返回任何东西之前。

这意味着“最后一次函数调用的结果”可能是由您的 current 调用限制函数引起的函数调用的结果。所以你对throttle() 的调用调用updateModelData() 然后返回未定义,因为updateModelData() 返回未定义。

这里有一些示例代码可以说明这一点:

var foo = (x) => x;
var leading = _.throttle(foo, DELAY, {leading: true, trailing: false}); //these are the default options for leading and trailing
var trailing = _.throttle(foo, DELAY, {leading: false, trailing: true});

leading(1); //Calls foo(1), returns 1
leading(2); //Doesn't call foo, returns 1, 
leading(3); //Doesn't call foo, returns 1

trailing(1); //Doesn't call foo, returns undefined
trailing(2); //Doesn't call foo, returns undefined

//DELAY ms later
//foo(2) is called, due to the most recent call to bar2

leading();  //Calls foo(), returns undefined 
leading(1); //Still returns undefined from above

trailing(); //Doesn't call foo, returns 2
trailing(1); //Doesn't call foo, returns 2

//Another DELAY ms later

leading("Whatever"); //Calls foo("Whatever"), returns "Whatever";

这是你的JSFiddle 的一个版本,它也让它稍微明显一些。


真的,你不应该仅仅为了获取它返回的最后一个值而调用一个函数,所以我建议你自己管理最后一个值,而不是依赖_.throttle 为你做这件事。例如:

var lastResultOfFoo;
var foo = function (x) {
    lastResultOfFoo = x;
    return x;
}

//OR (if you don't mind attaching arbitrary properties to functions)
var foo = function (x) {
    foo.lastResult = x;
    return x;
}

【讨论】:

  • 感谢您的明确解释,所以我建议您自己管理最后一个值 - 这是我试图避免的,但似乎 @987654329 的行为@re 返回的值很混乱,所以可能我会坚持自己处理这个值
  • @Maximus 根据您的操作,您可能会考虑事件发射器模式。这允许使用代码在生成时仅使用最新值,或者在需要时将其存储以供以后使用。
【解决方案2】:

以下代码可以正常工作:

var throttled = _.throttle(updateModelData, 1000);
var i = 0;

function updateModelData(data) {
    return data;
}

var interval = setInterval(function() {
    console.log(throttled(i++));

    if (i === 6) {
        clearInterval(interval);
        console.log('Last value: ' + throttled());
    }
}, 2000);

输出:

0
1
2
3
4
5
"Last value: 5"

DEMO

【讨论】:

  • 是的,这行得通,但稍后尝试通过调用throttled()获取最新值
  • 是的,感谢您的努力,但我仍然无法理解这种行为背后的逻辑
猜你喜欢
  • 2019-03-09
  • 1970-01-01
  • 2023-02-04
  • 2016-09-07
  • 2012-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-27
相关资源
最近更新 更多