setInterval 과 setTimeout 의 성능 문제

3216 단어 JavaScript
프로젝트 를 개발 할 때 는 몇 밀리초 만 에 한 번 의 조작 을 반복 하 는 수요 가 많다.setInterval 을 사용 하면 많은 성능 문 제 를 일 으 킬 수 있 습 니 다.
이유 중 하나: setInterval 코드 오류 무시
setInterval 은 자신 이 호출 한 코드 가 잘못 되 었 는 지 에 대해 무관심 한 습관 이 있다.
setInterval 에서 실 행 된 코드 가 어떤 이유 로 잘못 되면 이 코드 를 계속 호출 할 것 이라는 얘 기다.
우 리 는 아래 의 이 예 를 분석 해 보 자.
function a() {
  try {
    a.error();
  } catch(e) {
    throw(e);
  }
}
setInterval(a, 2000);

function b() {
  try {
    b.error();
  } catch (e) {
    throw(e);
  }
  setTimeout(b, 1000);
}
setTimeout(b, 2000);

원인 2: setInterval 네트워크 지연 무시
일정 시간 마다 Ajax 를 통과 한다 고 가정 해 봐. 서버 에 문의 하여 새로운 데이터 가 있 는 지 확인 하 세 요. (주의: 만약 당신 이 정말 이렇게 한다 면 아마 당신 이 잘못 한 것 같 습 니 다. "보상 성 폴 링" (backoff polling) 을 사용 하 는 것 을 권장 합 니 다.일부 원인 (서버 과부하, 임시 차단, 데이터 급증, 사용자 대역 폭 제한) 으로 인해 당신 의 요청 은 생각 보다 오래 걸 립 니 다.하지만 setInterval 은 개의 치 않 는 다.이것 은 여전히 정 해진 시간 에 따라 요청 을 계속 실행 합 니 다. 최종 적 으로 클 라 이언 트 네트워크 대기 열 은 Ajax 호출 을 가득 채 울 것 입 니 다.
우 리 는 아래 의 이 예 를 분석 해 보 자.
let n = 0, t = 0, u = 0, i;
const s = 'Stopping after 25 requests, to avoid killing jsfiddle’s server';

function a() {
  $.post('***', () => {
    --n;
  });
  ++n;
  ++t;
  $('#reqs').html(n + ' a() requests in progress!');
  if (t > 25) {
    clearInterval(i);
    $('#reqs').html(s);
  }
}

function b() {
  ++u;
  $.post('***', () => {
    $('#req2').html('b(): ' + new Date().toString());
    if (u <= 25) {
      setTimeout(b, 500);
    } else {
      $('#req2').html(s);
    }
  });
}


i = setInterval(a, 500);
setTimeout(b, 500);

원인 3: setInterval 은 실행 간격 을 보장 하지 않 습 니 다.
setTimeout 과 달리 시간 간격 이 되면 코드 가 실 행 될 수 있다 는 보장 은 없습니다.
만약 당신 이 호출 한 함수 가 비교적 오 랜 시간 이 걸 려 야만 완성 할 수 있다 면, 일부 호출 은 직접 무 시 될 것 입 니 다.
function slow() {
  $.ajax({
    url: '/echo/html/',
    async: false,
    data: {
      delay: 1
    },
    complete: function () {
    }
  });
  $('#reqs').text(~~((new Date() - start) / 100) + ' expected, ' + iters + ' actual');
  if (iters++ > 4) {
    $('#reqs').append('
Stopping after 5 iterations'); clearInterval(iv); } } let iv = setInterval(slow, 100); let start = +new Date(); let iters = 0;

setTimeout 은 이 문 제 를 해결 할 수 있 습 니 다.
 
setInterval 을 사용 하기 보 다 는 적당 한 시간 에 setTimeout 을 통 해 함수 자 체 를 호출 하 는 것 이 좋 습 니 다.
앞의 두 예제 에서 setInterval 을 사용 하 는 함수 a 가 모두 잘못 되 었 고 setTimeout 을 사용 하 는 함수 b 는 잘 표현 되 었 습 니 다.
만약 간격 이 같다 는 것 을 보증 해 야 한다 면 어떻게 합 니까?
이벤트 의 '등 속' 이 촉발 되 는 것 을 확실히 보장 하려 면 원 하 는 지연 으로 지난번 호출 에 걸 린 시간 을 뺀 다음 에 얻 은 차 이 를 지연 동적 으로 setTimeout 에 지정 할 수 있 습 니 다.하지만 주의해 야 할 것 은 자 바스 크 립 트 의 타 이 머 는 정확 하지 않다 는 점 이다.따라서 절대적 인 '평균' 지연 을 받 을 수 없습니다. setInterval 을 사용 하 더 라 도 안 됩 니 다. 원인 이 많 습 니 다 (예 를 들 어 쓰레기 회수, JavaScript 는 단일 스 레 드 입 니 다. 등등).또한 현재 브 라 우 저 는 최소 시간 초과 시간 을 4ms 에서 15ms 사이 로 고정 합 니 다.그 러 니 조금의 오차 도 없다 고 기대 하지 마라.
마지막 으로 마 이 클 은 setInterval 을 사용 하 느 냐 setTimeout 을 사용 하 느 냐 에 따라 먼저 프로젝트 의 기능 요구 에 따라 기능 을 실현 하 는 것 이 가장 중요 한 임무 라 고 주장 했다.만약 에 둘 다 사용 할 수 있 는 상황 에서 setTimeout 을 사용 하여 재 귀적 호출 을 실현 하여 더욱 좋 은 성능 최적화 를 실현 할 수 있다.

좋은 웹페이지 즐겨찾기