簡體   English   中英

lodash 去抖動在匿名函數中不起作用

[英]lodash debounce not working in anonymous function

您好,我似乎無法弄清楚為什么 debounce 函數在直接傳遞給 keyup 事件時會按預期工作; 但如果我將它包裝在一個匿名函數中,它就不起作用。

我有這個問題的小提琴: http : //jsfiddle.net/6hg95/1/

編輯:添加了我嘗試過的所有東西。

HTML

<input id='anonFunction'/>
<input id='noReturnAnonFunction'/>
<input id='exeDebouncedFunc'/>
<input id='function'/>
<div id='output'></div>

爪哇腳本

$(document).ready(function(){
    $('#anonFunction').on('keyup', function () {
        return _.debounce(debounceIt, 500, false); //Why does this differ from #function
    });
    $('#noReturnAnonFunction').on('keyup', function () {
        _.debounce(debounceIt, 500, false); //Not being executed
    });
    $('#exeDebouncedFunc').on('keyup', function () {
        _.debounce(debounceIt, 500, false)(); //Executing the debounced function results in wrong behaviour
    });
    $('#function').on('keyup', _.debounce(debounceIt, 500, false)); //This is working.
});

function debounceIt(){
    $('#output').append('debounced');
}

anonFunctionnoReturnAnonFunction不會觸發去抖動功能; 但最后一個function確實觸發了。 我不明白這是為什么。 有人可以幫我理解這一點嗎?

編輯好的,所以在#exeDebouncedFunc(您引用的那個)中沒有發生去抖動的原因是因為該函數是在匿名函數的范圍內執行的,而另一個 keyup 事件將在另一個匿名范圍內創建一個新函數; 因而燒制去抖動功能多次,你輸入的東西(而不是一次射擊這將是預期的行為;看到beviour的#function )?

能否請您解釋之間的差異#anonFunction#function 這又是一個界定為什么其中一個有效而另一個無效的問題嗎?

編輯好的,現在我明白為什么會這樣了。 這就是為什么我需要將它包裝在一個匿名函數中的原因:

小提琴: http : //jsfiddle.net/6hg95/5/

HTML

<input id='anonFunction'/>
<div id='output'></div>

爪哇腳本

(function(){
    var debounce = _.debounce(fireServerEvent, 500, false);

    $('#anonFunction').on('keyup', function () {
        //clear textfield
        $('#output').append('clearNotifications<br/>');
        debounce();
    });

    function fireServerEvent(){
        $('#output').append('serverEvent<br/>');
    }
})();

正如 Palpatim 解釋的那樣,原因在於_.debounce(...)返回一個函數,該函數在調用時會發揮其魔力。

因此,在您的#anonFunction示例中,您有一個鍵偵聽器,它在被調用時#anonFunction向調用者返回一個函數,而該函數對來自事件偵聽器的返回值不做任何事情。

這是_.debounce(...)定義的一個片段:

_.debounce
function (func, wait, immediate) {
    var timeout;
    return function() {
      var context = this, args = arguments;
      var later = function() {
        timeout = null;
        if (!immediate) func.apply(context, args);
      };
      if (immediate && !timeout) func.apply(context, args);
      clearTimeout(timeout);
      timeout = setTimeout(later, wait);
    };
  } 

您的關鍵事件偵聽器必須從_.debounce(...)調用返回的函數,或者您可以在非匿名示例中執行操作,並使用_.debounce(...)調用中的返回函數作為您的事件偵聽器.

想得更輕松

_.debounce 返回一個去抖動的函數! 所以,而不是思考

$el.on('keyup'), function(){
   _.debounce(doYourThing,500); //uh I want to debounce this
}

你寧願調用去抖動函數

var doYourThingDebounced = _.debounce(doYourThing, 500); //YES, this will always be debounced

$el.on('keyup', doYourThingDebounced);

debounce不執行該函數,它返回一個內置了 debounceness 的函數。

退貨

(Function) : 返回新的去抖動函數。

所以你的#function處理程序實際上是在做正確的事情,通過返回一個由 jQuery 用作 keyup 處理程序的函數。 要修復#noReturnAnonFunction示例,您可以簡單地在函數的上下文中執行去抖動函數:

$('#noReturnAnonFunction').on('keyup', function () {
    _.debounce(debounceIt, 500, false)(); // Immediately executes
});

但這會在您的去抖動周圍引入一個不必要的匿名函數包裝器。

您可以像這樣返回 debounce 函數:

(function(){
    var debounce = _.debounce(fireServerEvent, 500, false);

    $('#anonFunction').on('keyup', function () {
        //clear textfield
        $('#output').append('clearNotifications<br/>');
        return debounce();
    });

    function fireServerEvent(){
        $('#output').append('serverEvent<br/>');
    }
})();

更一般地說,如果您想要帶有尾隨行為的去抖動(考慮最后一次點擊,或者更可能是選擇輸入的最后一次更改),以及第一次點擊/更改時的視覺反饋,您將面臨同樣的問題。

這不起作用:

$(document).on('change', "#select", function() {
    $('.ajax-loader').show();
    _.debounce(processSelectChange, 1000);
});

這將是一個解決方案:

$(document).on('change', "#select", function() {
    $('.ajax-loader').show();
});
$(document).on('change', "#select", _.debounce(processSelectChange, 1000));

在尋找使用尾隨調用調用 debounce 的解決方案時遇到了這個問題,發現這篇文章對我很有幫助https ://newbedev.com/lodash-debounce-not-working-in-react: https : //newbedev.com/lodash-debounce-not-working-in-react

對於那些因為油門 / 去抖動不起作用而來到這里的人的解決方案 > 使用 FunctionComponent - 您需要通過 useRef() 存儲去抖動的函數:

export const ComponentName = (value = null) => {
  const [inputValue, setInputValue] = useState(value);

  const setServicesValue = value => Services.setValue(value);

  const setServicesValueDebounced = useRef(_.debounce(setServicesValue, 1000));

  const handleChange = ({ currentTarget: { value } }) => {
    setInputValue(value);
    setServicesValueDebounced.current(value);
  };

  return <input onChange={handleChange} value={inputValue} />;
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM