debounce 函數(shù)引起的思考

debounce 函數(shù)引起的思考

開發(fā)中我們經(jīng)常遇到這種情況,一個輸入框內(nèi)觸發(fā)onChange事件時調用接口章蚣,或者處理某件事情。但是我們就會發(fā)現(xiàn)每當我們每當輸入一個單詞的時候就會發(fā)現(xiàn)觸發(fā)了這個動作,是不是體驗不是很友好,如果等用戶輸入完了在執(zhí)行那該多好啊岳链,那我們可以在光標離開的時候觸發(fā),但是往往事與愿違劲件。產(chǎn)品說我想讓他實時搜索掸哑,那...约急。那是不是可以使用延時的方法,比如使用settimeout方法延時執(zhí)行這個方法苗分,比如延時1秒執(zhí)行厌蔽。那我們就可以使用計時器的方式去實現(xiàn)。

  • 我們可以看下面那個例子俭嘁,我們每輸入一個字符躺枕,控制臺就會打印一次服猪。

打開鏈接供填,可以看到具體實現(xiàn)
https://codesandbox.io/embed/x9q5nl2lv4

現(xiàn)在我們把讓面的代碼用下面的替換,然后在看控制臺的打印結果罢猪。

import React from "react";
import ReactDOM from "react-dom";
import { Input } from "antd";
import "./styles.css";
const Search = Input.Search;

class App extends React.Component {
  constructor(props) {
    super(props);

    this.waitSearch = null;
  }

  handleOnSearch = e => {
    const value = e.target.value;
    if (this.waitSearch) {
      clearTimeout(this.waitSearch);
    }
    this.waitSearch = setTimeout(() => console.log(value), 1000);
  };

  render() {
    return (
      <div>
        <Search
          placeholder="input search text"
          onChange={this.handleOnSearch}
          style={{ width: 200 }}
        />
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

我們聲明了一個全局變量waitSearch來控制settimeout的執(zhí)行近她,在你頻繁輸入的時候我們將你之前的任務都給清楚掉。這樣最后一個action將在你不觸發(fā)后的某個時間執(zhí)行膳帕。

  • 使用過lodash的同學就會發(fā)現(xiàn)有一個debounce函數(shù)可以滿足我們現(xiàn)在的場景,我們將上面的代碼替換成下面的代碼粘捎。
import React from "react";
import ReactDOM from "react-dom";
import { Input } from "antd";
import "./styles.css";
import _ from "lodash";
const Search = Input.Search;

class App extends React.Component {
  constructor(props) {
    super(props);

    this.debouncePrint = _.debounce(this.print, 1000);
  }

  handleOnSearch = e => {
    const value = e.target.value;
    this.debouncePrint(value);
  };

  print = value => {
    console.log(value);
  };

  render() {
    return (
      <div>
        <Search
          placeholder="input search text"
          onChange={this.handleOnSearch}
          style={{ width: 200 }}
        />
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

我們看到這句代碼,我們將print函數(shù)變成了debounce的了危彩。
this.debouncePrint = _.debounce(this.print, 1000);
我們將一個函數(shù)傳進去攒磨,然后返回了一個新的函數(shù)。那我們可以使用這個思路自己實現(xiàn)一個自己的debounce汤徽。

import React from "react";
import ReactDOM from "react-dom";
import { Input } from "antd";
import "./styles.css";
const Search = Input.Search;

class App extends React.Component {
  constructor(props) {
    super(props);

    this.debouncePrint = this.debounce(this.print, 1000);
  }

  handleOnSearch = e => {
    const value = e.target.value;
    this.debouncePrint(value);
  };

  print = value => {
    console.log(value);
  };

  debounce(fn, time) {
    let last = null;
    const that = this;
    return function(...args) {
      if (last) {
        clearTimeout(last);
      }
      last = setTimeout(() => {
        fn.apply(that, args);
      }, time);
    };
  }

  render() {
    return (
      <div>
        <Search
          placeholder="input search text"
          onChange={this.handleOnSearch}
          style={{ width: 200 }}
        />
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

是不是很好用娩缰,其實我們可以在進行深入考慮一下,我們知道Decorator修飾器可以修飾一個函數(shù)谒府,其實也是高階函數(shù)應用之一拼坎,只是修飾器使用了編譯特性,將函數(shù)上下文注入完疫。如果我們使用裝飾器的模式來寫一個debouce函數(shù)泰鸡,是不是更加簡單哪?


import React from "react";
import ReactDOM from "react-dom";
import { Input } from "antd";
import "./styles.css";
const Search = Input.Search;

const Debounce = (time: number) => {
  let last = null;
  return (_target, _property, descriptor) => {
    const fn = descriptor.value;
    descriptor.value = function(...args) {
      const that = this;
      clearTimeout(last);
      last = setTimeout(function() {
        fn.apply(that, args);
      }, time);
    };
    return descriptor;
  };
};

class App extends React.Component {
  handleOnSearch = e => {
    const value = e.target.value;
    this.print(value);
  };
  @Debounce(1000)
  print(value) {
    console.log(value);
  }

  render() {
    return (
      <div>
        <Search
          placeholder="input search text"
          onChange={this.handleOnSearch}
          style={{ width: 200 }}
        />
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

是不是更加簡單壳鹤,我們可以充分使用修飾器的功能盛龄,創(chuàng)造出一個個帶有特殊功能的函數(shù),讓你解放雙手芳誓。

使用redux-saga

redux-saga這個中間件可以很好的為我們處理異步邏輯余舶,當然也可以幫我們進行debounce。

function* handleInput({ input }) {
  // debounce by 500ms
  yield call(delay, 500)
  ...
}
  
function* watchInput() {
  yield takeLatest('INPUT_CHANGED', handleInput);
}

使用redux-observable

redux-observable是以rxjs進行的一個控制異步流程的插件兆沙,這個更加強大欧芽,當然也更難掌握,需要整個開發(fā)團隊的水平比較高葛圃,下面是rxjs5的寫法千扔。

const inputEpic = (action$) =>
  action$.ofType('INPUT_CHANGED')
    .debounceTime(500)

必備知識

  • 高階函數(shù)
  • apply函數(shù)的使用
  • decorator的使用
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末憎妙,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子曲楚,更是在濱河造成了極大的恐慌厘唾,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件龙誊,死亡現(xiàn)場離奇詭異抚垃,居然都是意外死亡,警方通過查閱死者的電腦和手機趟大,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門鹤树,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人逊朽,你說我怎么就攤上這事罕伯。” “怎么了叽讳?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵追他,是天一觀的道長。 經(jīng)常有香客問我岛蚤,道長邑狸,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任涤妒,我火速辦了婚禮单雾,結果婚禮上,老公的妹妹穿的比我還像新娘届腐。我一直安慰自己铁坎,他們只是感情好,可當我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布犁苏。 她就那樣靜靜地躺著硬萍,像睡著了一般。 火紅的嫁衣襯著肌膚如雪围详。 梳的紋絲不亂的頭發(fā)上朴乖,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天,我揣著相機與錄音助赞,去河邊找鬼买羞。 笑死,一個胖子當著我的面吹牛雹食,可吹牛的內(nèi)容都是我干的畜普。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼群叶,長吁一口氣:“原來是場噩夢啊……” “哼吃挑!你這毒婦竟也來了钝荡?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤舶衬,失蹤者是張志新(化名)和其女友劉穎埠通,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體逛犹,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡端辱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了虽画。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片舞蔽。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖狸捕,靈堂內(nèi)的尸體忽然破棺而出喷鸽,到底是詐尸還是另有隱情众雷,我是刑警寧澤灸拍,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站砾省,受9級特大地震影響鸡岗,放射性物質發(fā)生泄漏。R本人自食惡果不足惜编兄,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一轩性、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧狠鸳,春花似錦揣苏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至铅祸,卻和暖如春坑质,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背临梗。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工涡扼, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人盟庞。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓吃沪,卻偏偏與公主長得像,于是被迫代替她去往敵國和親什猖。 傳聞我的和親對象是個殘疾皇子票彪,可洞房花燭夜當晚...
    茶點故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結構(3).初始化時...
    歐辰_OSR閱讀 29,386評論 8 265
  • 長久以來萎津,面向對象在 JavaScript 編程范式中占據(jù)著主導地位。不過抹镊,最近人們對函數(shù)式編程的興趣正在增長锉屈。函...
    神刀閱讀 466評論 0 0
  • 路過病房時,又看到一統(tǒng)在開導新病人垮耳。 我站在門口望了一眼颈渊,一統(tǒng)也看到了我,點頭向他示意终佛,他回以微笑俊嗽。 新病人情緒失...
    青禾Cyril閱讀 228評論 0 0
  • 說起創(chuàng)業(yè),對于我來說铃彰,也許還很年輕绍豁,只是有幸和兩位朋友一起做事。我們做鄉(xiāng)村旅游牙捉。 鄉(xiāng)村市場近幾年持續(xù)火爆竹揍,很多如鄉(xiāng)...
    TT米樂閱讀 218評論 0 0
  • 談談近日的感受带到,也算是文字的一種宣泄昧碉。 自2017年以來,看的網(wǎng)上的心靈雞湯揽惹、勵志段子越來越多了被饿,感覺...
    是苔呀閱讀 278評論 0 0