기능 조절의 목적
함수 조절은 기능을 조절하고 성능을 어느 정도 최적화하는 데 사용된다고 말 그대로 이해하면 됩니다. 예를 들어 DOM 작업은 DOM이 아닌 작업보다 더 효율적입니다. 상호 작용에는 더 많은 메모리와 CPU 시간이 필요합니다. 너무 많은 DOM 관련 작업을 연속해서 수행하려고 하면 브라우저가 중단되고 때로는 충돌이 발생할 수도 있습니다. 특히 IE에서 onresize를 사용하면 이벤트 핸들러를 사용하면 브라우저 크기가 조정될 때 이벤트가 계속해서 발생하기 쉽습니다. DOM에 액세스하려는 경우 onresize 이벤트 핸들러 내부 작동 시 변경 빈도가 높으면 브라우저가 중단될 수 있습니다. 또 다른 예로 일반적인 검색 기능의 경우 일반적으로 keyup 이벤트를 바인딩하고 키보드를 누를 때마다 검색합니다. 그러나 우리의 목적은 주로 어떤 콘텐츠를 입력할 때마다 검색하는 것입니다. 이러한 문제를 해결하기 위해 타이머를 사용하여 기능을 조절할 수 있습니다.
함수 제한의 원리
일부 코드는 중단 없이 계속해서 반복적으로 실행될 수 없습니다. 함수가 처음 호출되면 지정된 간격 후에 코드를 실행하도록 타이머가 생성됩니다. 함수가 두 번째 호출되면 이전 타이머를 지우고 다른 타이머를 설정합니다. 이전 타이머가 이미 실행된 경우 이 작업은 의미가 없습니다. 단, 이전 타이머가 아직 실행되지 않은 경우 실제로는 새로운 타이머로 교체됩니다. 목적은 실행 요청이 일정 시간 동안 중지된 후에만 기능을 실행하는 것입니다.
기본 기능 조절 모드
var processor = { timeoutId: null, //实际进行处理的方法 performProcessing: function(){ //实际执行的代码 }, //初始处理调用的方法 process: function(){ clearTimeout(this.timeoutId); var that = this; this.timeoutId = setTimeout(function(){ that.performProcessing(); }, 100); } }; //尝试开始执行 processor.process();
예시 시나리오: 일반 검색 기능 구현
① 기능 조절을 사용하지 않고 키업 이벤트 처리 기능을 입력에 바인딩하고 콘솔에 입력한 내용을 출력합니다.
테스트 메인 코드:
<input id="search" type="text" name="search">
function queryData(text){ console.log("搜索:" + text); } var input = document.getElementById("search"); input.addEventListener("keyup", function(event){ queryData(this.value); });
결과는 그림과 같습니다.
이 경우에는 매번 키보드 키를 누르면 한번 출력되었습니다. 짧은 콘텐츠가 14번 출력되었습니다. 매번 Ajax 쿼리 요청이었다면 14번의 요청이 전송되었을 것입니다. 성능의 소비를 상상할 수 있습니다.
②기본 기능 스로틀링 모드를 사용하는 경우.
테스트 메인 코드:
<input id="search" type="text" name="search">
function queryData(text){ console.log("搜索:" + text); } var input = document.getElementById("search"); input.addEventListener("keyup", function(event){ throttle(queryData, null, 500, this.value); // queryData(this.value); }); function throttle(fn,context,delay,text){ clearTimeout(fn.timeoutId); fn.timeoutId = setTimeout(function(){ fn.call(context,text); },delay); }
결과는 그림과 같습니다.
이 경우 두 입력 사이의 간격을 로 설정했기 때문에 많은 내용이 입력되고 한 번만 출력되었음을 알 수 있습니다. 실제로 테스트 중에는 500ms가 소요되며, 상황에 따라 애플리케이션을 구성할 수 있습니다. 분명히 이것은 성능 측면에서 크게 최적화되었습니다. 그러나 이 경우에는 아래와 같이 새로운 문제가 발생합니다.
글쎄, 아마도 단서가 없을 수도 있습니다. 실제로 문제는 계속해서 많은 내용을 입력하는데, 두 입력 사이의 간격이 설정한 지연 값보다 작으면 queryData 검색 함수가 절대 호출되지 않는다는 것입니다. 실제로 우리가 선호하는 것은 특정 시간 값에 도달하면 이 검색 기능을 한 번 실행해야 한다는 것입니다. 따라서 기능 조절의 개선된 모델이 있습니다.
③기능 제한 강화 버전
테스트된 주요 코드:
<input id="search" type="text" name="search">
function queryData(text){ console.log("搜索:" + text); } var input = document.getElementById("search"); input.addEventListener("keyup", function(event){ throttle(queryData, null, 500, this.value,1000); // throttle(queryData, null, 500, this.value); // queryData(this.value); }); function throttle(fn,context,delay,text,mustApplyTime){ clearTimeout(fn.timer); fn._cur=Date.now(); //记录当前时间 if(!fn._start){ //若该函数是第一次调用,则直接设置_start,即开始时间,为_cur,即此刻的时间 fn._start=fn._cur; } if(fn._cur-fn._start>mustApplyTime){ <br> //当前时间与上一次函数被执行的时间作差,与mustApplyTime比较,若大于,则必须执行一次函数,若小于,则重新设置计时器 fn.call(context,text); fn._start=fn._cur; }else{ fn.timer=setTimeout(function(){ fn.call(context,text); },deley); } }
테스트 결과는 아래와 같습니다.
물론 연속 입력을 하면 일정 시간이 지나면 queryData 함수가 필연적으로 호출되지만 자주 호출되지는 않습니다. 이는 사용자 경험에 영향을 주지 않고 비용을 절감한다는 목적을 달성합니다.
IV 추가 최적화
더 나아가 스로틀 기능을 호출하기 전에 입력 내용을 판단할 수 있습니다. 값이 비어 있거나 값이 변경되지 않은 경우 다시 호출할 필요가 없습니다. 여기서는 자세히 설명하지 않겠습니다.