타이머 사용의 함정

타이머를 사용하는 과정에서 타이머의 일부 세부 사항을 이해하지 못하면 타이머의 함정에 빠질 가능성이 높습니다. setTimeout 함수는 적시성 측면에서 많은 본질적인 단점을 가지고 있으므로 일부 시간 정확도 요구 사항에 대해서는 If를 비교하십시오. 수요가 높으므로 일부 다른 솔루션을 목표 방식으로 채택해야 합니다.

1. 현재 작업의 실행 시간이 너무 길면 만료 타이머 작업의 실행에 영향을 미칩니다.

setTimeout을 사용할 때 콜백 함수의 실행이 설정된 예상 값보다 오래 걸릴 수 있는 요인은 여러 가지가 있는데, 그 중 하나는 현재 작업의 실행 시간이 너무 길어서 타이머에 의해 설정된 작업이 실행되지 않는 경우이다. 지연됩니다. 먼저 다음 코드를 살펴보겠습니다.

function bar() {
    
    
    console.log('bar')
}
function foo() {
    
    
    setTimeout(bar, 0);
    for (let i = 0; i < 5000; i++) {
    
    
        let i = 5+8+8+8
        console.log(i)
    }
}
foo()

이 코드에서 setTimeout은 foo 함수 실행 시 지연이 0인 콜백 작업을 설정하는 데 사용되며, 콜백 작업을 설정한 후 foo 함수는 for 루프를 5000번 계속 실행합니다.

setTimeout으로 설정한 콜백 작업은 메시지 큐에 넣어 다음 실행을 대기하며 바로 실행되지는 않으며, 메시지 큐의 다음 작업을 실행하려면 현재 작업이 실행될 때까지 기다려야 한다. 코드 필요 for 루프는 5000번 실행되므로 현재 작업의 실행 시간이 길어집니다. 이는 필연적으로 다음 작업의 실행 시간에 영향을 미칩니다.

2. setTimeout에 대한 중첩된 호출이 있는 경우 시스템은 최소 시간 간격을 4밀리초로 설정합니다.

즉, 타이머 함수에 타이머 호출을 중첩하면 타이머의 실행 시간도 연장됩니다. 먼저 다음 코드를 살펴볼 수 있습니다.

function cb() {
    
     setTimeout(cb, 0); }
setTimeout(cb, 0);

위의 코드에 문제가 있나요?

아래 그림과 같이 Performance를 통해 이 코드의 실행 과정을 기록할 수 있습니다.

여기에 이미지 설명을 삽입하세요.

위 그림의 세로선은 타이머의 함수 콜백 과정으로, 그림에서 알 수 있듯이 처음 5번 호출의 시간 간격은 상대적으로 작고, 중첩된 호출은 5번을 초과한다. 후속 호출은 4밀리초입니다. 이런 일이 발생하는 이유는 Chrome에서 타이머가 중첩되어 5회 이상 호출되면 시스템은 함수 메서드가 차단된 것으로 판단하고, 타이머 호출 간격이 4밀리초 미만이면 브라우저는 시간 간격을 통화 간 간격은 4밀리초로 설정됩니다.

따라서 일부 높은 실시간 요구 사항에는 setTimeout을 사용하는 것이 적합하지 않습니다.예를 들어 JavaScript 애니메이션을 구현하기 위해 setTimeout을 사용하는 것은 그리 좋은 생각이 아닙니다.

3. 비활성 페이지의 경우 setTimeout의 최소 실행 간격은 1000밀리초입니다.

이전의 4밀리초 지연 외에도 쉽게 간과할 수 있는 또 다른 점이 있는데, 바로 비활성 페이지의 최소 타이머 값이 1000밀리초보다 크다는 것입니다. 최소 타이머 값은 시간 간격이 1000밀리초입니다. 이는 백그라운드 페이지의 로딩 손실을 최적화하고 전력 소비를 줄이기 위한 것입니다. 타이머를 사용할 때 이 점에 주의해야 합니다.

4. 지연된 실행 시간은 최대값을 갖습니다.

타이머의 콜백 함수 시간이 실제 설정된 값에 비해 지연된다는 점을 아는 것 외에 또 한 가지 주의할 점이 있는데, 크롬, 사파리, 파이어폭스 모두 32비트를 사용하여 지연 값을 저장하는데, 최대 32bit만 저장할 수 있는 숫자는 2147483647ms인데, 이는 setTimeout으로 설정한 지연 값이 2147483647ms(약 24.8일)보다 크면 오버플로가 발생해 타이머가 즉시 실행된다는 뜻이다. 다음 코드를 실행할 수 있습니다.

function showName(){
    
    
  console.log(" 立即执行了 ")
}
var timerID = setTimeout(showName,2147483648);// 会被理解调用执行

실행 후 바로 이 코드가 실행되는 것을 확인할 수 있습니다. 하지만 지연 값을 2147483647ms 미만의 값으로 수정하면 실행에는 문제가 없습니다.

5. setTimeout을 사용하여 설정된 콜백 함수에서 이는 직관적이지 않습니다.

setTimeout에 의해 연기된 콜백 함수가 객체의 메소드인 경우 메소드의 this 키워드는 정의된 객체가 아닌 전역 환경을 가리킵니다. 이 점은 앞서 소개할 때도 언급한 바 있는데, 다음 코드의 실행 결과를 확인할 수 있습니다.

var name= 1;
var MyObj = {
    
    
  name: 2,
  showName: function(){
    
    
    console.log(this.name);
  }
}
setTimeout(MyObj.showName,1000)

이 코드가 컴파일될 때 실행 컨텍스트에서 전역 창으로 설정되기 때문에 출력은 1이고, 엄격 모드인 경우 정의되지 않음으로 설정됩니다.

그렇다면 이 문제를 해결하는 방법은 무엇입니까? 일반적으로 다음 두 가지 방법을 사용할 수 있습니다.

첫 번째는 아래와 같이 익명 함수에서 MyObj.showName을 실행하는 것입니다.

// 箭头函数
setTimeout(() => {
    
    
    MyObj.showName()
}, 1000);
// 或者 function 函数
setTimeout(function() {
    
    
  MyObj.showName();
}, 1000)

두 번째 방법은 바인딩 메소드를 사용하여 showName을 MyObj에 바인딩하는 것입니다. 코드는 다음과 같습니다.

setTimeout(MyObj.showName.bind(MyObj), 1000)

추천

출처blog.csdn.net/qq_44721831/article/details/128819504