먼저 스로틀이 무엇인지 이해합시다
1. 정의
물방울 형태로 물이 흘러 나올 때까지 수도꼭지를 조이면 가끔씩 물 한 방울이 흘러 나옵니다.
즉, 실행주기가 미리 설정되고 동작이 호출되는 시간이 실행 사이클보다 크거나 동일하면 조치가 실행되고 다음 새주기가 입력됩니다.
인터페이스 정의 :
* 주파수 제어를 반환하면 함수를 연속적으로 반환하면 작업 실행 주파수는 시간/ 지연* @param 지연 {번호} 지연 시간, 단위 밀리 초* @param action {function} 관련 함수를 요청하고 실제 응용 프로그램에서 호출 해야하는 기능* @return {function} 클라이언트 호출 함수*/ 스로틀 (지연, 조치)을 반환합니다.2. 간단한 구현
var 스로틀 = 함수 (지연, 동작) {var last = 0return function () {var cur = +new date () if (curr -last> delay) {action.apply (this, arguments) last = curr}}}이 조절 기능을 아래에서 신중하게 설명하겠습니다.
브라우저 DOM 이벤트에서는 일부 이벤트가 사용자의 작업과 함께 지속적으로 트리거됩니다. 예를 들어, 브라우저 창 크기를 조정하고 브라우저 페이지를 스크롤하고 MouseMove를 스크롤하십시오. 즉, 사용자가 이러한 브라우저 작업을 트리거 할 때 해당 이벤트 처리 방법이 스크립트에 바인딩되면이 메소드가 지속적으로 트리거됩니다.
이벤트 처리 방법이 상대적으로 크고 복잡한 DOM 운영이 상대적으로 크고, 이러한 이벤트를 지속적으로 트리거하면 성능 손실이 발생하여 사용자 경험이 감소하기 때문에 이벤트 처리 방법이 비교적 크고, DOM 작업이 지속적으로 트리거되기 때문입니다 (느린 UI 응답, 브라우저가 고착 등). 따라서 일반적으로 실행을 지연시키기 위해 해당 이벤트에 논리를 추가합니다.
일반적으로 다음 코드를 사용 하여이 기능을 구현합니다.
var count = 0; function testfn () {console.log (count ++); } // 브라우저가 크기를 조정하면 // 1. 이전 타이머를 지우십시오. // 2. 실제 함수 testfn을 100 밀리 초로 지연시키기 위해 타이머를 추가하여 Window.onResize = function () {var timer = null; 클리어 타임 아웃 (타이머); timer = settimeout (function () {testfn ();}, 100);};신중한 학생들은 위의 코드가 실제로 잘못되었다는 것을 알게 될 것입니다. 이것은 초보자가 할 문제입니다. Settimeout 함수의 반환 값은 상대적인 글로벌 변수로 저장되어야합니다. 그렇지 않으면 크기 조정이 크기를 조정할 때마다 새 타이머가 생성되며, 이는 우리가 보내는 효과를 달성하지 못합니다.
그래서 우리는 코드를 수정했습니다.
var timer = null; wind timer = settimeout (function () {testfn ();}, 100);};현재 코드는 정상이지만 또 다른 새로운 문제가 있습니다. 글로벌 변수 타이머가 생성됩니다. 이것은 우리가보고 싶지 않은 것입니다. 이 페이지에 다른 기능이 있으면 타이머라고도합니다. 다른 코드는 이전에 충돌을 일으킬 것입니다. 이 문제를 해결하려면 JavaScript : Closures Closures의 언어 기능을 사용해야합니다. 독자는 MDN의 관련 지식에 대해 배울 수 있습니다. 수정 된 코드는 다음과 같습니다.
/*** 함수 스로틀 링 방법* @Param 함수 fn 지연 호출 함수* @Param 번호 지연 지연* @return 함수 실행 지연*/var 스로틀 = 함수 (fn, 지연) {var timer = null; return function () {cleartimeout (타이머); TIMER = settimeout (function () {fn ();}, Delay); }}; Window.onResize = 스로틀 (TestFn, 200, 1000);우리는 클로저 기능 (스로틀 스로틀링)을 사용하여 타이머를 내부적으로 놓고 지연 처리 기능을 반환합니다. 이러한 방식으로, 타이머 변수는 외부에 보이지 않지만 내부 지연 함수가 트리거되면 타이머 변수에도 액세스 할 수 있습니다.
물론,이 글쓰기 방법은 초보자가 이해하기 쉽지 않습니다. 우리는 글쓰기 방법을 변경하여 다음을 이해할 수 있습니다.
var Throttle = function (fn, delay) {var timer = null; return function () {cleartimeout (타이머); TIMER = settimeout (function () {fn ();}, Delay); }}; var f = 스로틀 (testfn, 200); window.onresize = function () {f ();};다음은 관점입니다. 호출 후 스로틀에 의해 반환 된 기능은 onresize가 트리거 될 때 호출 해야하는 실제 함수입니다.
이제이 방법은 완벽에 가깝지만 실제로 사용되는 것은 아닙니다. 예를 들어:
사용자가 지속적으로 브라우저 창 크기를 크기로 크기를 조정하면 지연 처리 기능이 한 번에 실행되지 않습니다.
따라서 다른 기능을 추가해야합니다. 사용자가 크기 조정을 트리거 할 때 특정 기간 내에 적어도 한 번 트리거해야합니다. 일정 기간 내에,이 판단 조건은 현재 시간 시간을 소지 할 수 있으며, 각 함수 호출은 마지막 통화 시간에서 현재 시간을 빼고, 차이가 일정 시간보다 크면 직접 전송 될 것이라고 판단합니다. 그렇지 않으면 시간 초과 지연 논리를 따를 것입니다.
다음 코드에서 지적 해야하는 것은 다음과 같습니다.
이전 변수의 기능은 타이머의 기능과 유사합니다. 둘 다 마지막 시간을 기록하는 식별자이며 상대적인 글로벌 변수 여야합니다.
로직 프로세스가 논리를 "적어도 한 번 트리거"하는 경우, 현재 시간을 재설정하려면 함수 호출을 완료해야합니다. 요컨대, 그것은 실제로 다음 시간에 비해 현재의 것입니다.
/*** 함수 스로 틀링 방법* @param 함수 fn 지연 호출 기능* @param 번호 지연 지연 시간* @param 번호 실행 지연을위한 @return 함수 메소드*/var 스로틀 = 함수 (fn, 지연, 적어도) {var timer = null; var previous = null; return function () {var now = +new date (); if (! previous) 이전 = 지금; if (지금 - 이전> 적어도) {fn (); // 마지막 시작 시간을이 시간의 종료 시간으로 재설정하면 이전 = 지금; } else {cleartimeout (타이머); TIMER = settimeout (function () {fn ();}, Delay); }}};관행:
창이 스크롤 할 때, 즉 사용자가 페이지를 아래쪽으로 스크롤 할 때 DOM 위치를 계산하는 등과 같은 일부 방법을 조절 해야하는 스로틀 장면을 시뮬레이션합니다. DOM 요소의 지속적인 작동이 필요합니다.
전체 코드는 다음과 같습니다.
<! docType html> <html lang = "en"> <head> <meta charset = "utf-8"> <title> 스로틀 </title> </head> <body> <div style = "height : 5000px"> <div id = "demo"style = "위치;"> ">"> ">"> "demo = 0, demo = 0, document.getElementById ( '데모'); function testfn () {demo.innerhtml += 'testfn은' +++ count +'time <br>';} var shrottle = function (fn, delay, inder) {var timer = null; var previous = null; return function () {var now = +new date (); if (! previous) 이전 = 지금; if (적어도 && now- 이전> 적어도) {fn (); // 마지막 시작 시간을이 시간의 종료 시간으로 재설정하면 이전 = 지금; 클리어 타임 아웃 (타이머); } else {cleartimeout (타이머); TIMER = settimeout (function () {fn (); previous = null;}, 지연); }}}}; Window.onscroll = 스로틀 (Testfn, 200); // window.onscroll = 스로틀 (testfn, 500, 1000); </script> </body> </html>우리는 효과를 테스트하기 위해 두 가지 사례를 사용합니다. 즉, 적어도 적어도 적어도 추가하지 않고 추가하지 않습니다.
// case 1window.onscroll = 스로틀 (testfn, 200); // case 2window.onscroll = 스로틀 (testfn, 200, 500);
사례 1은 다음과 같이 나타납니다. 테스트 FN은 페이지 스크롤링 프로세스 중에 호출되지 않으며 (중지 할 수 없음) 중지 될 때까지 한 번 호출됩니다. 즉, 스로틀의 마지막 설정 시간이 실행되면 효과는 그림에 표시됩니다.
사례 2는 다음과 같이 나타납니다. 페이지 스크롤링 프로세스 중에 (중지 할 수 없음), TestFN은 처음으로 500ms (적어도 지연 로직)로 지연된 다음 적어도 500ms를 실행합니다. 효과는 그림과 같이입니다
위에서 볼 수 있듯이, 우리가 달성하려는 효과가 도입되었고 예제가 제공됩니다. 도움이 필요한 친구들에게 도움이되기를 바랍니다. 독자들은 다음과 같이 다음과 같이 자체적으로 일부 보조 최적화에 대해 생각할 수 있습니다.