-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
635 lines (229 loc) · 35.7 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
<!DOCTYPE html>
<html class="theme-next muse use-motion" lang="zh-Hans">
<head>
<meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
<meta name="theme-color" content="#222">
<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
<link href="/blog/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />
<link href="/blog/css/main.css?v=6.0.0" rel="stylesheet" type="text/css" />
<link rel="apple-touch-icon" sizes="180x180" href="/blog/images/apple-touch-icon-next.png?v=6.0.0">
<link rel="icon" type="image/png" sizes="32x32" href="/blog/images/favicon-32x32-next.png?v=6.0.0">
<link rel="icon" type="image/png" sizes="16x16" href="/blog/images/favicon-16x16-next.png?v=6.0.0">
<link rel="mask-icon" href="/blog/images/logo.svg?v=6.0.0" color="#222">
<meta name="keywords" content="Hexo, NexT" />
<meta name="description" content="节流函数节流函数算是老生常谈了,项目里面必备的基础函数,但你真的用对了吗?深入研究了一下,发现自己用的确实不太对。首先了解一下节流函数的概念 节流函数:顾名思义,像节流阀一样均匀的执行,把密集的重复调用,通过设置定时器,使函数在固定的间隔时间调用,在一段时间内,等时间间隔的调用多次,这里跟的bounce函数一定要区分开。 debounce: 中文意思,防反跳,防止密集的重复请求,即一定时间间隔内的">
<meta property="og:type" content="article">
<meta property="og:title" content="老生常谈节流函数">
<meta property="og:url" content="https://github.com/blog/2017/12/04/老生常谈节流函数/index.html">
<meta property="og:site_name" content="jing's blog">
<meta property="og:description" content="节流函数节流函数算是老生常谈了,项目里面必备的基础函数,但你真的用对了吗?深入研究了一下,发现自己用的确实不太对。首先了解一下节流函数的概念 节流函数:顾名思义,像节流阀一样均匀的执行,把密集的重复调用,通过设置定时器,使函数在固定的间隔时间调用,在一段时间内,等时间间隔的调用多次,这里跟的bounce函数一定要区分开。 debounce: 中文意思,防反跳,防止密集的重复请求,即一定时间间隔内的">
<meta property="og:locale" content="zh-Hans">
<meta property="og:updated_time" content="2018-01-06T15:05:53.000Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="老生常谈节流函数">
<meta name="twitter:description" content="节流函数节流函数算是老生常谈了,项目里面必备的基础函数,但你真的用对了吗?深入研究了一下,发现自己用的确实不太对。首先了解一下节流函数的概念 节流函数:顾名思义,像节流阀一样均匀的执行,把密集的重复调用,通过设置定时器,使函数在固定的间隔时间调用,在一段时间内,等时间间隔的调用多次,这里跟的bounce函数一定要区分开。 debounce: 中文意思,防反跳,防止密集的重复请求,即一定时间间隔内的">
<script type="text/javascript" id="hexo.configurations">
var NexT = window.NexT || {};
var CONFIG = {
root: '/blog/',
scheme: 'Muse',
version: '6.0.0',
sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
fancybox: false,
fastclick: false,
lazyload: false,
tabs: true,
motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
duoshuo: {
userId: '0',
author: '博主'
},
algolia: {
applicationID: '',
apiKey: '',
indexName: '',
hits: {"per_page":10},
labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
}
};
</script>
<link rel="canonical" href="https://github.com/blog/2017/12/04/老生常谈节流函数/"/>
<title>jing's blog</title>
</head>
<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">
<div class="container sidebar-position-left
page-home">
<div class="headband"></div>
<header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
<div class="header-inner"> <div class="site-brand-wrapper">
<div class="site-meta ">
<div class="custom-logo-site-title">
<a href="/blog/" class="brand" rel="start">
<span class="logo-line-before"><i></i></span>
<span class="site-title">jing's blog</span>
<span class="logo-line-after"><i></i></span>
</a>
</div>
<p class="site-subtitle">面朝前端,冬冷夏凉</p>
</div>
<div class="site-nav-toggle">
<button>
<span class="btn-bar"></span>
<span class="btn-bar"></span>
<span class="btn-bar"></span>
</button>
</div>
</div>
<nav class="site-nav">
<ul id="menu" class="menu">
<li class="menu-item menu-item-home">
<a href="/blog/" rel="section">
<i class="menu-item-icon fa fa-fw fa-home"></i> <br />
首页
</a>
</li>
<li class="menu-item menu-item-tags">
<a href="/blog/tags/" rel="section">
<i class="menu-item-icon fa fa-fw fa-tags"></i> <br />
标签
</a>
</li>
<li class="menu-item menu-item-archives">
<a href="/blog/archives/" rel="section">
<i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
归档
</a>
</li>
</ul>
</nav>
</div>
</header>
<main id="main" class="main">
<div class="main-inner">
<div class="content-wrap">
<div id="content" class="content">
<section id="posts" class="posts-expand">
<article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
<div class="post-block">
<link itemprop="mainEntityOfPage" href="https://github.com/blog/blog/2017/12/04/老生常谈节流函数/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="杨雪静">
<meta itemprop="description" content="">
<meta itemprop="image" content="/blog/images/avatar.gif">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="jing's blog">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/blog/2017/12/04/老生常谈节流函数/" itemprop="url">老生常谈节流函数</a></h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建于" itemprop="dateCreated datePublished" datetime="2017-12-04T21:17:17+08:00">2017-12-04</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h3 id="节流函数"><a href="#节流函数" class="headerlink" title="节流函数"></a>节流函数</h3><p>节流函数算是老生常谈了,项目里面必备的基础函数,但你真的用对了吗?深入研究了一下,发现自己用的确实不太对。首先了解一下节流函数的概念</p>
<p>节流函数:顾名思义,像节流阀一样均匀的执行,把密集的重复调用,通过设置定时器,使函数在固定的间隔时间调用,在一段时间内,等时间间隔的调用多次,这里跟的bounce函数一定要区分开。</p>
<p>debounce: 中文意思,防反跳,防止密集的重复请求,即一定时间间隔内的密集请求都丢弃,等待间隔时间后不再请求再去执行,在一段时间内,可能只调用一次。</p>
<p>分清楚这两个概念之后,先看一段代码:</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> generateThrottle = <span class="function"><span class="keyword">function</span> (<span class="params">throttleTime</span>) </span>{</span><br><span class="line"> <span class="keyword">let</span> time = <span class="built_in">Date</span>.now()</span><br><span class="line"> <span class="keyword">return</span> <span class="function"><span class="keyword">function</span> (<span class="params">now</span>) </span>{</span><br><span class="line"> <span class="comment">// 如果没有设置节流时间, 使用默认配置的时间</span></span><br><span class="line"> <span class="keyword">if</span> (now - time > (throttleTime || AppConfig.THROTTLE_TIME)) {</span><br><span class="line"> time = now</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> resizeThrottle = generateThrottle()</span><br><span class="line"><span class="comment">// 监听窗口resize</span></span><br><span class="line"><span class="built_in">window</span>.addEventListener(<span class="string">'resize'</span>, event => {</span><br><span class="line"> <span class="comment">// 发布滚动事件</span></span><br><span class="line"> resizeThrottle(<span class="built_in">Date</span>.now()) && dosomething()</span><br><span class="line">})</span><br></pre></td></tr></table></figure>
<p>这是我们项目里面的节流函数,咋一看没啥问题,直到项目出现了一个很偶现的bug,最后发现是dosomething()这个函数偶尔会不执行引起的。我们再来仔细看一下代码,当时间间隔大于THROTTLE_TIME时函数返回ture,否则就不返回,如果最后一次缩放窗口和上次时间间隔小于THROTTLE_TIME,然后停止缩放,那么这个时候dosomething()就不执行了,最后导致dosomething的状态还停留在上一次缩放,导致bug。所以当你希望停止缩放后再执行一次dosomething(),那么上面这个函数显然是不合理的!</p>
<p>然后我们重写了这个节流函数如下:</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 首次调用创建一个定时器,最多每隔 mustRunDelay 时间调用一次该函数</span></span><br><span class="line"><span class="comment"> * @param fn 执行函数</span></span><br><span class="line"><span class="comment"> * @param delay 时间间隔</span></span><br><span class="line"><span class="comment"> * @param mustRunDelay 必然触发执行的时间间隔</span></span><br><span class="line"><span class="comment"> * @returns {Function}</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">var</span> throttle = <span class="function"><span class="keyword">function</span>(<span class="params">fn, delay, mustRunDelay</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> timer = <span class="literal">null</span>;</span><br><span class="line"> <span class="keyword">var</span> previous;</span><br><span class="line"> <span class="keyword">return</span> <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> context = <span class="keyword">this</span>, args = <span class="built_in">arguments</span>, now = +<span class="keyword">new</span> <span class="built_in">Date</span>();</span><br><span class="line"> clearTimeout(timer);</span><br><span class="line"> <span class="keyword">if</span>(!previous) {</span><br><span class="line"> previous = now;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(now - previous >= mustRunDelay){</span><br><span class="line"> fn.apply(context, args);</span><br><span class="line"> previous = now;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> timer = setTimeout(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</span><br><span class="line"> fn.apply(context, args)</span><br><span class="line"> }, delay)</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">function testFn () {</span><br><span class="line"> console.log(111111)</span><br><span class="line">}</span><br><span class="line">window.onresize = throttle(testFn, 50, 1000)</span><br></pre></td></tr></table></figure>
<p>这个函数首次调用会创建一个定时器,当重复调用的时候会不断的清空并重置定时器,当时间间隔大于等于mustRunDelay时,调用该函数,并更新时间戳。这样就保证了函数每隔mustRunDelay后重复调用该函数,并且在最后一次触发之后的delay时间后最后一次执行该函数。这个函数就基本能满足我们业务的需求了。如果你想首次调用能够立即执行该函数或者最后一次调用并不触发该函数,那么继续往下看。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 创建并返回一个像节流阀一样的函数,当重复调用函数的时候,最多每隔 wait毫秒调用一次该函数</span></span><br><span class="line"><span class="comment"> * @param func 执行函数</span></span><br><span class="line"><span class="comment"> * @param wait 时间间隔</span></span><br><span class="line"><span class="comment"> * @param options 如果你想禁用第一次首先执行的话,传递{leading: false},</span></span><br><span class="line"><span class="comment"> * 如果你想禁用最后一次执行的话,传递{trailing: false}</span></span><br><span class="line"><span class="comment"> * @returns {Function}</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">throttle</span> (<span class="params">fn, wait, options</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> context, args, result;</span><br><span class="line"> <span class="keyword">var</span> timeout = <span class="literal">null</span>;</span><br><span class="line"> <span class="keyword">var</span> previous = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">if</span> (!options) options = {};</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">var</span> later = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> previous = options.leading === <span class="literal">false</span> ? <span class="number">0</span> : <span class="keyword">new</span> <span class="built_in">Date</span>().getTime();</span><br><span class="line"> timeout = <span class="literal">null</span>;</span><br><span class="line"> result = fn.apply(context, args);</span><br><span class="line"> contxt = args = <span class="literal">null</span>;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">return</span> <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="keyword">var</span> now = <span class="keyword">new</span> <span class="built_in">Date</span>().getTime();</span><br><span class="line"> <span class="keyword">if</span>(!previous && options.leading === <span class="literal">false</span>) previous = now;</span><br><span class="line"> <span class="keyword">var</span> remaining = wait - (now - previous);</span><br><span class="line"> context = <span class="keyword">this</span>;</span><br><span class="line"> args = <span class="built_in">arguments</span>;</span><br><span class="line"> <span class="keyword">if</span>(remaining <=<span class="number">0</span> || remaining > wait) {</span><br><span class="line"> <span class="keyword">if</span> (timeout){</span><br><span class="line"> clearTimeout(timeout);</span><br><span class="line"> timeout = <span class="literal">null</span>;</span><br><span class="line"> }</span><br><span class="line"> previous = now;</span><br><span class="line"> result = fn.apply(context, args);</span><br><span class="line"> <span class="keyword">if</span>(!timeout) context = args = <span class="literal">null</span>;</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span>(!timeout && options.trailing !== <span class="literal">false</span>){</span><br><span class="line"> timeout = setTimeout(later, remaining)</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> result;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">function testFn () {</span><br><span class="line"> console.log(111111)</span><br><span class="line">}</span><br><span class="line">window.onresize = throttle(testFn, 200, {leading:false})</span><br></pre></td></tr></table></figure>
<p>这个节流函数就相当的完美了,默认是首次立即执行fn,最后一次调用之后的wait时间后执行,当重复调用的时候,最多每隔wait时间间隔调用一次fn。也可以通过传参来禁用第一次执行和最后一次执行。</p>
<h4 id="debounce函数"><a href="#debounce函数" class="headerlink" title="debounce函数"></a>debounce函数</h4><p>然后我们再来看看高程上面的节流函数,函数每次调用的时候先清空定时器,再设置一个新的定时器,当窗口缩放的时候会不断的触发throttle,这个时候实际上fn只有在最后一次触发throttle后100ms执行,而且只执行一次。所以这个并不是真正意义上面的节流函数。而是一个debounce函数,丢弃一些密集重复的操作。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">throttle</span> (<span class="params">method, context</span>) </span>{</span><br><span class="line"> clearTimeout(method.tId);</span><br><span class="line"> method.tId = setTimeout(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</span><br><span class="line"> method.call(context)</span><br><span class="line"> }, <span class="number">100</span>)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fn</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="number">111111</span>)</span><br><span class="line">}</span><br><span class="line"><span class="built_in">window</span>.onresize = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</span><br><span class="line"> throttle(fn);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>下面这个函数写法不一样,其实结果也是一样,只执行一次</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">let throttle = function(fn, delay){</span><br><span class="line"> let timer = null;</span><br><span class="line"> return function(){</span><br><span class="line"> let content = this,</span><br><span class="line"> args = arguments;</span><br><span class="line"> clearTimeout(timer);</span><br><span class="line"> timer = setTimeout(function(){</span><br><span class="line"> fn.apply(content, args)</span><br><span class="line"> }, delay)</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">function testFn () {</span><br><span class="line"> console.log(111111)</span><br><span class="line">}</span><br><span class="line">window.onresize = throttle(testFn, 1000)</span><br></pre></td></tr></table></figure>
<p>debounce函数的使用场景很多,比如用户输入验证,在用户的输入过程中不断请求可以都丢弃,停止输入后在进行验证。 再比如下拉刷新,如何第一次请求的时候执行,多次重复请求的话,直接丢弃掉,停止操作后再进行请求。像这种刷新需要立即请求的情况上面的函数就满足不了了,然后就有了下面的函数</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 防反跳 fn函数在最后一次调用时刻的wait毫秒之后执行!</span></span><br><span class="line"><span class="comment"> * @param fn 执行函数</span></span><br><span class="line"><span class="comment"> * @param wait 时间间隔</span></span><br><span class="line"><span class="comment"> * @param immediate 为true,debounce会在wait 时间间隔的开始调用这个函数</span></span><br><span class="line"><span class="comment"> * @returns {Function}</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">debounce</span>(<span class="params">fn, wait, immediate</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> timeout, args, context, timestamp, result;</span><br><span class="line"> <span class="keyword">var</span> later = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="keyword">var</span> last = <span class="keyword">new</span> <span class="built_in">Date</span>().getTime() - timestamp;</span><br><span class="line"> <span class="keyword">if</span> (last < wait && last >= <span class="number">0</span>) {</span><br><span class="line"> timeout = setTimeout(later, wait - last);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> timeout = <span class="literal">null</span>;</span><br><span class="line"> <span class="keyword">if</span>(!immediate) {</span><br><span class="line"> result = fn.apply(context, args);</span><br><span class="line"> context = args = <span class="literal">null</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> context = <span class="keyword">this</span>;</span><br><span class="line"> args = <span class="built_in">arguments</span>;</span><br><span class="line"> timestamp = <span class="keyword">new</span> <span class="built_in">Date</span>().getTime(); <span class="comment">//每次触发时更新</span></span><br><span class="line"> <span class="keyword">var</span> callNow = immediate && !timeout;</span><br><span class="line"> <span class="keyword">if</span>(!timeout) {</span><br><span class="line"> timeout = setTimeout(later, wait);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (callNow) {</span><br><span class="line"> result = fn.apply(context, args);</span><br><span class="line"> context = args = <span class="literal">null</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> result;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">testFn</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="number">111111</span>)</span><br><span class="line">}</span><br><span class="line"><span class="built_in">window</span>.onresize = debounce(testFn, <span class="number">300</span>)</span><br></pre></td></tr></table></figure>
<p>1.当immediate 为true时,立即执行fn,wait时间间隔内频繁调用,不断的重置定时器,并不会触发fn,wait时间之后通过将定时器清空,等待wait间隔之后再次调用,则立即执行fn。之后如此循环往复。</p>
<p>使用场景:比如微博下拉刷新,首次下拉请求,中间频繁的下拉并不会触发请求,一定时间后再刷新会重新触发</p>
<p>2.当immediate 为false,不会立即执行该函数,wait 时间间隔内频繁调用,不断重置定时器,wait 时间间隔后,如果无触发,则清空定时器,触发fn,只执行一次fn;</p>
<p>使用场景:用户输入验证,不在输入过程中处理,停止输入后进行验证</p>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</div>
</article>
</section>
</div>
</div>
<div class="sidebar-toggle">
<div class="sidebar-toggle-line-wrap">
<span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
<span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
<span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
</div>
</div>
<aside id="sidebar" class="sidebar">
<div class="sidebar-inner">
<section class="site-overview-wrap sidebar-panel sidebar-panel-active">
<div class="site-overview">
<div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
<img class="site-author-image" itemprop="image"
src="/blog/images/avatar.gif"
alt="杨雪静" />
<p class="site-author-name" itemprop="name">杨雪静</p>
<p class="site-description motion-element" itemprop="description">前端笔记</p>
</div>
<nav class="site-state motion-element">
<div class="site-state-item site-state-posts">
<a href="/blog/archives/">
<span class="site-state-item-count">1</span>
<span class="site-state-item-name">日志</span>
</a>
</div>
</nav>
</div>
</section>
</div>
</aside>
</div>
</main>
<footer id="footer" class="footer">
<div class="footer-inner">
<div class="copyright">© <span itemprop="copyrightYear">2018</span>
<span class="with-love">
<i class="fa fa-user"></i>
</span>
<span class="author" itemprop="copyrightHolder">杨雪静</span>
</div>
<div class="powered-by">由 <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a> 强力驱动</div>
<span class="post-meta-divider">|</span>
<div class="theme-info">主题 — <a class="theme-link" target="_blank" href="https://github.com/theme-next/hexo-theme-next">NexT.Muse</a> v6.0.0</div>
</div>
</footer>
<div class="back-to-top">
<i class="fa fa-arrow-up"></i>
</div>
</div>
<script type="text/javascript">
if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
window.Promise = null;
}
</script>
<script type="text/javascript" src="/blog/lib/jquery/index.js?v=2.1.3"></script>
<script type="text/javascript" src="/blog/lib/velocity/velocity.min.js?v=1.2.1"></script>
<script type="text/javascript" src="/blog/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
<script type="text/javascript" src="/blog/js/src/utils.js?v=6.0.0"></script>
<script type="text/javascript" src="/blog/js/src/motion.js?v=6.0.0"></script>
<script type="text/javascript" src="/blog/js/src/bootstrap.js?v=6.0.0"></script>
</body>
</html>