René's URL Explorer Experiment


Title: 手写一个节流函数 throttle · Issue #92 · sisterAn/JavaScript-Algorithms · GitHub

Open Graph Title: 手写一个节流函数 throttle · Issue #92 · sisterAn/JavaScript-Algorithms

X Title: 手写一个节流函数 throttle · Issue #92 · sisterAn/JavaScript-Algorithms

Description: debounce 与 throttle 是开发中常用的高阶函数,作用都是为了防止函数被高频调用,换句话说就是,用来控制某个函数在一定时间内执行多少次。 使用场景 比如绑定响应鼠标移动、窗口大小调整、滚屏等事件时,绑定的函数触发的频率会很频繁。若稍处理函数微复杂,需要较多的运算执行时间和资源,往往会出现延迟,甚至导致假死或者卡顿感。为了优化性能,这时就很有必要使用 debounce 或 throttle 了。 debounce 与 throttle 区别 防抖 (debo...

Open Graph Description: debounce 与 throttle 是开发中常用的高阶函数,作用都是为了防止函数被高频调用,换句话说就是,用来控制某个函数在一定时间内执行多少次。 使用场景 比如绑定响应鼠标移动、窗口大小调整、滚屏等事件时,绑定的函数触发的频率会很频繁。若稍处理函数微复杂,需要较多的运算执行时间和资源,往往会出现延迟,甚至导致假死或者卡顿感。为了优化性能,这时就很有必要使用 debounce 或 thr...

X Description: debounce 与 throttle 是开发中常用的高阶函数,作用都是为了防止函数被高频调用,换句话说就是,用来控制某个函数在一定时间内执行多少次。 使用场景 比如绑定响应鼠标移动、窗口大小调整、滚屏等事件时,绑定的函数触发的频率会很频繁。若稍处理函数微复杂,需要较多的运算执行时间和资源,往往会出现延迟,甚至导致假死或者卡顿感。为了优化性能,这时就很有必要使用 debounce 或 thr...

Opengraph URL: https://github.com/sisterAn/JavaScript-Algorithms/issues/92

X: @github

direct link

Domain: github.com


Hey, it has json ld scripts:
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"手写一个节流函数 throttle","articleBody":"`debounce` 与 `throttle` 是开发中常用的高阶函数,作用都是为了防止函数被高频调用,换句话说就是,用来控制某个函数在一定时间内执行多少次。\r\n\r\n### 使用场景\r\n\r\n比如绑定响应鼠标移动、窗口大小调整、滚屏等事件时,绑定的函数触发的频率会很频繁。若稍处理函数微复杂,需要较多的运算执行时间和资源,往往会出现延迟,甚至导致假死或者卡顿感。为了优化性能,这时就很有必要使用 `debounce` 或 `throttle` 了。\r\n\r\n### `debounce` 与 `throttle` 区别\r\n\r\n防抖 (**debounce**) :多次触发,只在最后**一次触发**时,执行目标函数。\r\n\r\n节流(**throttle**):限制目标函数调用的**频率**,比如:1s内不能调用2次。\r\n\r\n### 手写一个 `throttle`  \r\n\r\n实现方案有以下两种:\r\n\r\n- 第一种是用时间戳来判断是否已到执行时间,记录上次执行的时间戳,然后每次触发事件执行回调,回调中判断当前时间戳距离上次执行时间戳的间隔是否已经达到时间差(Xms) ,如果是则执行,并更新上次执行的时间戳,如此循环。\r\n- 第二种方法是使用定时器,比如当 `scroll` 事件刚触发时,打印一个 *hello world*,然后设置个 `1000ms` 的定时器,此后每次触发 `scroll` 事件触发回调,如果已经存在定时器,则回调不执行方法,直到定时器触发,`handler` 被清除,然后重新设置定时器。\r\n\r\n这里我们采用第一种方案来实现,通过闭包保存一个 `previous` 变量,每次触发 `throttle` 函数时判断当前时间和 `previous` 的时间差,如果这段时间差小于等待时间,那就忽略本次事件触发。如果大于等待时间就把 `previous` 设置为当前时间并执行函数 fn。\r\n\r\n我们来一步步实现,首先实现用闭包保存 `previous` 变量。\r\n\r\n```js\r\nconst throttle = (fn, wait) =\u003e {\r\n\t// 上一次执行该函数的时间\r\n  let previous = 0\r\n  return function(...args) {\r\n    console.log(previous)\r\n    ...\r\n  }\r\n}\r\n```\r\n\r\n执行 `throttle` 函数后会返回一个新的 `function` ,我们命名为 `betterFn` 。\r\n\r\n```js\r\nconst betterFn = function(...args) {\r\n  console.log(previous)\r\n    ...\r\n}\r\n```\r\n\r\n`betterFn` 函数中可以获取到 `previous` 变量值也可以修改,在回调监听或事件触发时就会执行 `betterFn` ,即 `betterFn()`,所以在这个新函数内判断当前时间和 `previous` 的时间差即可。\r\n\r\n```js\r\nconst betterFn = function(...args) {\r\n  let now = +new Date();\r\n  if (now - previous \u003e wait) {\r\n    previous = now\r\n    // 执行 fn 函数\r\n    fn.apply(this, args)\r\n  }\r\n}\r\n```\r\n\r\n结合上面两段代码就实现了节流函数,所以完整的实现如下。\r\n\r\n```js\r\n// fn 是需要执行的函数\r\n// wait 是时间间隔\r\nconst throttle = (fn, wait = 50) =\u003e {\r\n  // 上一次执行 fn 的时间\r\n  let previous = 0\r\n  // 将 throttle 处理结果当作函数返回\r\n  return function(...args) {\r\n    // 获取当前时间,转换成时间戳,单位毫秒\r\n    let now = +new Date()\r\n    // 将当前时间和上一次执行函数的时间进行对比\r\n    // 大于等待时间就把 previous 设置为当前时间并执行函数 fn\r\n    if (now - previous \u003e wait) {\r\n      previous = now\r\n      fn.apply(this, args)\r\n    }\r\n  }\r\n}\r\n\r\n// DEMO\r\n// 执行 throttle 函数返回新函数\r\nconst betterFn = throttle(() =\u003e console.log('fn 函数执行了'), 1000)\r\n// 每 10 毫秒执行一次 betterFn 函数,但是只有时间差大于 1000 时才会执行 fn\r\nsetInterval(betterFn, 10)\r\n```\r\n\r\n### underscore 源码解读\r\n\r\n上述代码实现了一个简单的节流函数,不过 `underscore` 实现了更高级的功能,即新增了两个功能\r\n\r\n- 配置是否需要响应事件刚开始的那次回调( `leading` 参数,`false` 时忽略)\r\n- 配置是否需要响应事件结束后的那次回调( `trailing` 参数,`false` 时忽略)\r\n\r\n配置 `{ leading: false }` 时,事件刚开始的那次回调不执行;配置 `{ trailing: false }` 时,事件结束后的那次回调不执行,不过需要注意的是,这两者不能同时配置。\r\n\r\n所以在 `underscore` 中的节流函数有 3 种调用方式,默认的(有头有尾),设置 `{ leading: false }` 的,以及设置 `{ trailing: false }` 的。上面说过实现 `throttle` 的方案有 2 种,一种是通过时间戳判断,另一种是通过定时器创建和销毁来控制。\r\n\r\n第一种方案实现这 3 种调用方式存在一个问题,即事件停止触发时无法响应回调,所以 `{ trailing: true }` 时无法生效。\r\n\r\n第二种方案来实现也存在一个问题,因为定时器是延迟执行的,所以事件停止触发时必然会响应回调,所以 `{ trailing: false }` 时无法生效。\r\n\r\n`underscore` 采用的方案是两种方案搭配使用来实现这个功能。\r\n\r\n```js\r\nconst throttle = function(func, wait, options) {\r\n  var timeout, context, args, result;\r\n  \r\n  // 上一次执行回调的时间戳\r\n  var previous = 0;\r\n  \r\n  // 无传入参数时,初始化 options 为空对象\r\n  if (!options) options = {};\r\n\r\n  var later = function() {\r\n    // 当设置 { leading: false } 时\r\n    // 每次触发回调函数后设置 previous 为 0\r\n    // 不然为当前时间\r\n    previous = options.leading === false ? 0 : _.now();\r\n    \r\n    // 防止内存泄漏,置为 null 便于后面根据 !timeout 设置新的 timeout\r\n    timeout = null;\r\n    \r\n    // 执行函数\r\n    result = func.apply(context, args);\r\n    if (!timeout) context = args = null;\r\n  };\r\n\r\n  // 每次触发事件回调都执行这个函数\r\n  // 函数内判断是否执行 func\r\n  // func 才是我们业务层代码想要执行的函数\r\n  var throttled = function() {\r\n    \r\n    // 记录当前时间\r\n    var now = _.now();\r\n    \r\n    // 第一次执行时(此时 previous 为 0,之后为上一次时间戳)\r\n    // 并且设置了 { leading: false }(表示第一次回调不执行)\r\n    // 此时设置 previous 为当前值,表示刚执行过,本次就不执行了\r\n    if (!previous \u0026\u0026 options.leading === false) previous = now;\r\n    \r\n    // 距离下次触发 func 还需要等待的时间\r\n    var remaining = wait - (now - previous);\r\n    context = this;\r\n    args = arguments;\r\n    \r\n    // 要么是到了间隔时间了,随即触发方法(remaining \u003c= 0)\r\n    // 要么是没有传入 {leading: false},且第一次触发回调,即立即触发\r\n    // 此时 previous 为 0,wait - (now - previous) 也满足 \u003c= 0\r\n    // 之后便会把 previous 值迅速置为 now\r\n    if (remaining \u003c= 0 || remaining \u003e wait) {\r\n      if (timeout) {\r\n        clearTimeout(timeout);\r\n        \r\n        // clearTimeout(timeout) 并不会把 timeout 设为 null\r\n        // 手动设置,便于后续判断\r\n        timeout = null;\r\n      }\r\n      \r\n      // 设置 previous 为当前时间\r\n      previous = now;\r\n      \r\n      // 执行 func 函数\r\n      result = func.apply(context, args);\r\n      if (!timeout) context = args = null;\r\n    } else if (!timeout \u0026\u0026 options.trailing !== false) {\r\n      // 最后一次需要触发的情况\r\n      // 如果已经存在一个定时器,则不会进入该 if 分支\r\n      // 如果 {trailing: false},即最后一次不需要触发了,也不会进入这个分支\r\n      // 间隔 remaining milliseconds 后触发 later 方法\r\n      timeout = setTimeout(later, remaining);\r\n    }\r\n    return result;\r\n  };\r\n\r\n  // 手动取消\r\n  throttled.cancel = function() {\r\n    clearTimeout(timeout);\r\n    previous = 0;\r\n    timeout = context = args = null;\r\n  };\r\n\r\n  // 执行 _.throttle 返回 throttled 函数\r\n  return throttled;\r\n};\r\n```\r\n\r\n### 参考\r\n\r\n[【进阶 7-1 期】深入浅出节流函数 throttle](https://github.com/yygmind/blog/issues/38)\r\n\r\n[浅谈节流与防抖](https://github.com/sisterAn/blog/issues/36)","author":{"url":"https://github.com/sisterAn","@type":"Person","name":"sisterAn"},"datePublished":"2020-08-10T00:09:56.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":4},"url":"https://github.com/92/JavaScript-Algorithms/issues/92"}

route-pattern/_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format)
route-controllervoltron_issues_fragments
route-actionissue_layout
fetch-noncev2:67124e06-3066-b6ab-6b13-1805412b4590
current-catalog-service-hash81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114
request-id9F5A:9CC2A:366086:4C4E4C:696A6864
html-safe-nonce2e892b813c2fd6ca12bbdbd43954f3c5b71f99c3c043bb2e522dcc709675d714
visitor-payloadeyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI5RjVBOjlDQzJBOjM2NjA4Njo0QzRFNEM6Njk2QTY4NjQiLCJ2aXNpdG9yX2lkIjoiNTU2NTIxNDY0NzMzODU1OTU4OCIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9
visitor-hmac3ce411bee29c01930d7d79fd1b5a660830e23c1e14754edca20fc493484d7e52
hovercard-subject-tagissue:675799222
github-keyboard-shortcutsrepository,issues,copilot
google-site-verificationApib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I
octolytics-urlhttps://collector.github.com/github/collect
analytics-location///voltron/issues_fragments/issue_layout
fb:app_id1401488693436528
apple-itunes-appapp-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/sisterAn/JavaScript-Algorithms/92/issue_layout
twitter:imagehttps://opengraph.githubassets.com/79bfb6560b65a08a1fee3bfdb076e7a5968a110eb1c47f9840164c7f39d37022/sisterAn/JavaScript-Algorithms/issues/92
twitter:cardsummary_large_image
og:imagehttps://opengraph.githubassets.com/79bfb6560b65a08a1fee3bfdb076e7a5968a110eb1c47f9840164c7f39d37022/sisterAn/JavaScript-Algorithms/issues/92
og:image:altdebounce 与 throttle 是开发中常用的高阶函数,作用都是为了防止函数被高频调用,换句话说就是,用来控制某个函数在一定时间内执行多少次。 使用场景 比如绑定响应鼠标移动、窗口大小调整、滚屏等事件时,绑定的函数触发的频率会很频繁。若稍处理函数微复杂,需要较多的运算执行时间和资源,往往会出现延迟,甚至导致假死或者卡顿感。为了优化性能,这时就很有必要使用 debounce 或 thr...
og:image:width1200
og:image:height600
og:site_nameGitHub
og:typeobject
og:author:usernamesisterAn
hostnamegithub.com
expected-hostnamegithub.com
None6fea32d5b7276b841b7a803796d9715bc6cfb31ed549fdf9de2948ac25d12ba6
turbo-cache-controlno-preview
go-importgithub.com/sisterAn/JavaScript-Algorithms git https://github.com/sisterAn/JavaScript-Algorithms.git
octolytics-dimension-user_id19721451
octolytics-dimension-user_loginsisterAn
octolytics-dimension-repository_id252061924
octolytics-dimension-repository_nwosisterAn/JavaScript-Algorithms
octolytics-dimension-repository_publictrue
octolytics-dimension-repository_is_forkfalse
octolytics-dimension-repository_network_root_id252061924
octolytics-dimension-repository_network_root_nwosisterAn/JavaScript-Algorithms
turbo-body-classeslogged-out env-production page-responsive
disable-turbofalse
browser-stats-urlhttps://api.github.com/_private/browser/stats
browser-errors-urlhttps://api.github.com/_private/browser/errors
releasef2d9f6432a5a115ec709295ae70623f33bb80aee
ui-targetfull
theme-color#1e2327
color-schemelight dark

Links:

Skip to contenthttps://github.com/sisterAn/JavaScript-Algorithms/issues/92#start-of-content
https://github.com/
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2FsisterAn%2FJavaScript-Algorithms%2Fissues%2F92
GitHub CopilotWrite better code with AIhttps://github.com/features/copilot
GitHub SparkBuild and deploy intelligent appshttps://github.com/features/spark
GitHub ModelsManage and compare promptshttps://github.com/features/models
MCP RegistryNewIntegrate external toolshttps://github.com/mcp
ActionsAutomate any workflowhttps://github.com/features/actions
CodespacesInstant dev environmentshttps://github.com/features/codespaces
IssuesPlan and track workhttps://github.com/features/issues
Code ReviewManage code changeshttps://github.com/features/code-review
GitHub Advanced SecurityFind and fix vulnerabilitieshttps://github.com/security/advanced-security
Code securitySecure your code as you buildhttps://github.com/security/advanced-security/code-security
Secret protectionStop leaks before they starthttps://github.com/security/advanced-security/secret-protection
Why GitHubhttps://github.com/why-github
Documentationhttps://docs.github.com
Bloghttps://github.blog
Changeloghttps://github.blog/changelog
Marketplacehttps://github.com/marketplace
View all featureshttps://github.com/features
Enterpriseshttps://github.com/enterprise
Small and medium teamshttps://github.com/team
Startupshttps://github.com/enterprise/startups
Nonprofitshttps://github.com/solutions/industry/nonprofits
App Modernizationhttps://github.com/solutions/use-case/app-modernization
DevSecOpshttps://github.com/solutions/use-case/devsecops
DevOpshttps://github.com/solutions/use-case/devops
CI/CDhttps://github.com/solutions/use-case/ci-cd
View all use caseshttps://github.com/solutions/use-case
Healthcarehttps://github.com/solutions/industry/healthcare
Financial serviceshttps://github.com/solutions/industry/financial-services
Manufacturinghttps://github.com/solutions/industry/manufacturing
Governmenthttps://github.com/solutions/industry/government
View all industrieshttps://github.com/solutions/industry
View all solutionshttps://github.com/solutions
AIhttps://github.com/resources/articles?topic=ai
Software Developmenthttps://github.com/resources/articles?topic=software-development
DevOpshttps://github.com/resources/articles?topic=devops
Securityhttps://github.com/resources/articles?topic=security
View all topicshttps://github.com/resources/articles
Customer storieshttps://github.com/customer-stories
Events & webinarshttps://github.com/resources/events
Ebooks & reportshttps://github.com/resources/whitepapers
Business insightshttps://github.com/solutions/executive-insights
GitHub Skillshttps://skills.github.com
Documentationhttps://docs.github.com
Customer supporthttps://support.github.com
Community forumhttps://github.com/orgs/community/discussions
Trust centerhttps://github.com/trust-center
Partnershttps://github.com/partners
GitHub SponsorsFund open source developershttps://github.com/sponsors
Security Labhttps://securitylab.github.com
Maintainer Communityhttps://maintainers.github.com
Acceleratorhttps://github.com/accelerator
Archive Programhttps://archiveprogram.github.com
Topicshttps://github.com/topics
Trendinghttps://github.com/trending
Collectionshttps://github.com/collections
Enterprise platformAI-powered developer platformhttps://github.com/enterprise
GitHub Advanced SecurityEnterprise-grade security featureshttps://github.com/security/advanced-security
Copilot for BusinessEnterprise-grade AI featureshttps://github.com/features/copilot/copilot-business
Premium SupportEnterprise-grade 24/7 supporthttps://github.com/premium-support
Pricinghttps://github.com/pricing
Search syntax tipshttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
documentationhttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2FsisterAn%2FJavaScript-Algorithms%2Fissues%2F92
Sign up https://github.com/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fvoltron%2Fissues_fragments%2Fissue_layout&source=header-repo&source_repo=sisterAn%2FJavaScript-Algorithms
Reloadhttps://github.com/sisterAn/JavaScript-Algorithms/issues/92
Reloadhttps://github.com/sisterAn/JavaScript-Algorithms/issues/92
Reloadhttps://github.com/sisterAn/JavaScript-Algorithms/issues/92
sisterAn https://github.com/sisterAn
JavaScript-Algorithmshttps://github.com/sisterAn/JavaScript-Algorithms
Notifications https://github.com/login?return_to=%2FsisterAn%2FJavaScript-Algorithms
Fork 649 https://github.com/login?return_to=%2FsisterAn%2FJavaScript-Algorithms
Star 5.7k https://github.com/login?return_to=%2FsisterAn%2FJavaScript-Algorithms
Code https://github.com/sisterAn/JavaScript-Algorithms
Issues 158 https://github.com/sisterAn/JavaScript-Algorithms/issues
Pull requests 0 https://github.com/sisterAn/JavaScript-Algorithms/pulls
Actions https://github.com/sisterAn/JavaScript-Algorithms/actions
Projects 0 https://github.com/sisterAn/JavaScript-Algorithms/projects
Security Uh oh! There was an error while loading. Please reload this page. https://github.com/sisterAn/JavaScript-Algorithms/security
Please reload this pagehttps://github.com/sisterAn/JavaScript-Algorithms/issues/92
Insights https://github.com/sisterAn/JavaScript-Algorithms/pulse
Code https://github.com/sisterAn/JavaScript-Algorithms
Issues https://github.com/sisterAn/JavaScript-Algorithms/issues
Pull requests https://github.com/sisterAn/JavaScript-Algorithms/pulls
Actions https://github.com/sisterAn/JavaScript-Algorithms/actions
Projects https://github.com/sisterAn/JavaScript-Algorithms/projects
Security https://github.com/sisterAn/JavaScript-Algorithms/security
Insights https://github.com/sisterAn/JavaScript-Algorithms/pulse
New issuehttps://github.com/login?return_to=https://github.com/sisterAn/JavaScript-Algorithms/issues/92
New issuehttps://github.com/login?return_to=https://github.com/sisterAn/JavaScript-Algorithms/issues/92
手写一个节流函数 throttlehttps://github.com/sisterAn/JavaScript-Algorithms/issues/92#top
手写源码https://github.com/sisterAn/JavaScript-Algorithms/issues?q=state%3Aopen%20label%3A%22%E6%89%8B%E5%86%99%E6%BA%90%E7%A0%81%22
https://github.com/sisterAn
https://github.com/sisterAn
sisterAnhttps://github.com/sisterAn
on Aug 10, 2020https://github.com/sisterAn/JavaScript-Algorithms/issues/92#issue-675799222
【进阶 7-1 期】深入浅出节流函数 throttlehttps://github.com/yygmind/blog/issues/38
浅谈节流与防抖https://github.com/sisterAn/blog/issues/36
手写源码https://github.com/sisterAn/JavaScript-Algorithms/issues?q=state%3Aopen%20label%3A%22%E6%89%8B%E5%86%99%E6%BA%90%E7%A0%81%22
https://github.com
Termshttps://docs.github.com/site-policy/github-terms/github-terms-of-service
Privacyhttps://docs.github.com/site-policy/privacy-policies/github-privacy-statement
Securityhttps://github.com/security
Statushttps://www.githubstatus.com/
Communityhttps://github.community/
Docshttps://docs.github.com/
Contacthttps://support.github.com?tags=dotcom-footer

Viewport: width=device-width


URLs of crawlers that visited me.