js 0 ms 지연 타이머 구현 몇 가지 방식

5709 단어 js타이머
이틀 동안'시간 맞 추 는 setTimeout 을 어떻게 실현 합 니까?'의 글 은 면접 문제 에서 기원 되 었 습 니 다.setTimeout 을 시간 에 맞 추 는 방법 이 있 습 니까?구체 적 인 글 내용 은 부록[1]을 볼 수 있 습 니 다.본 후에 저 는 setTimeout 이라는 함수 에 대한 탐구 흥 미 를 불 러 일 으 켰 습 니 다.그래서 MDN 에서 관련 문 서 를 다시 찾 아 보 았 습 니 다.그 중에서[최소 지연>=4ms]의 점 을 언급 했 기 때문에 setTimeout 을 사용 하면 0 ms 지연 시간 을 실현 할 수 없 는 타 이 머 를 실현 하려 면 참고 링크 를 제공 합 니 다[2].작가 의 실현 방향 은 postmessage 를 통 해 시 뮬 레이 션 을 하고 setTimeout 의 제한 을 돌아 서 0 ms 지연 시간 을 실현 하 는 타 이 머 를 실현 하 는 것 이다.쉽게 말 하면 매크로 임 무 를 수행 하여 리 셋 을 수행 하 는 것 이다.먼저 어떻게 실현 되 는 지 구체 적 으로 살 펴 보 자.

(function() {
 var timeouts = [];
 var messageName = "zero-timeout-message";
 // Like setTimeout, but only takes a function argument.  There's
 // no time argument (always zero) and no arguments (you have to use a closure)
 function setZeroTimeout(fn) {
  timeouts.push(fn);
  window.postMessage(messageName, "*");
 }
 function handleMessage(event) {
  if (event.source == window && event.data == messageName) {
   event.stopPropagation();
   if (timeouts.length > 0) {
    var fn = timeouts.shift();
    fn();
   }
  }
 }

 window.addEventListener("message", handleMessage, true);

 // Add the one thing we want added to the window object.
 window.setZeroTimeout = setZeroTimeout;
})();

저 자 는 또한 demo 페이지[3]를 제공 하여 setTimeout(0)과 비교 하여 제 브 라 우 저의 실행 결 과 는 다음 과 같 습 니 다.
100 iterations of setZeroTimeout took 15 milliseconds.
100 iterations of setTimeout(0) took 488 milliseconds.
결과 에 따 르 면 setZero Timeout 의 집행 은 setTimeout 보다 백 배 나 빨 라 졌 고 이것 은 큰 향상 이 었 다.오늘 토론 하고 자 하 는 것 은 상술 한 방식 을 제외 하고 어떤 방식 으로 0 ms 지연 의 타 이 머 를 실현 할 수 있 는 지 하 는 것 입 니 다.우선,우 리 는 우리 가 사용자 정의 타 이 머 는 비동기 적 이 고,그 다음은 가능 한 한 빨리 실 행 될 수 있 는 지 확인 해 야 합 니 다.비동기 로 말하자면 js 는 여러 가지 해결 방안 을 제 공 했 기 때문에 우 리 는 하나하나 검증 할 수 있다.
여러 가지 실현 방식 을 깊이 토론 하기 전에 제 공 된 setTimeout 비교 버 전 은 다음 과 같 습 니 다.그 다음 에 사용자 정의 실현 방안 은 모두 setTimeout 버 전의 실행 시간 과 비교 되 고 코드 는 비교적 간단 합 니 다.

(function() {
 let i = 0;
 const start = Date.now();
 function test() {
  if(i++ < 100) {
   setTimeout(test);
  } else {
   console.log('setTimeout    :', Date.now() - start);
  }
 }
 setTimeout(test);
})();
queueMicrotask
quueMicrotask 라 는 api 는 마이크로 작업 을 추가 할 수 있 습 니 다.사용 이 비교적 간단 하고 리 셋 함 수 를 직접 전달 하면 됩 니 다.구체 적 으로 다음 과 같 습 니 다.

(function() {
 function setZeroTimeout(fn) {
  queueMicrotask(fn);
 }
 let i = 0;
 const start = Date.now();
 function test() {
  if(i++ < 100) {
   setZeroTimeout(test);
  } else {
   console.log('setZeroTimeout    :', Date.now() - start);
  }
 }
 setZeroTimeout(test);
})();
setTimeout 버 전과 비교 한 결과 다음 과 같 습 니 다.
setZeroTimeout 실행 시간:2
setTimeout 실행 시간:490
이 API 에 대한 소 개 는 MDN 에 상세 한 설명 이 있 으 면 소 개 를 하지 않 습 니 다.여기 서 한 가지 더 말씀 드 리 겠 습 니 다.규범 화 된 문서 의 설명 에 따라 대부분 requestAnimation Frame()과 requestIdleCallback()등 api 를 사용 하 는 것 을 추천 합 니 다.quueMicrotask 는 렌 더 링 을 막 기 때문에 좋 은 실천 이 아 닙 니 다.
async/await
async/await 는 전단 개발 자 에 게 있어 서 없어 서 는 안 될 것 입 니 다.여기 서도 우 리 는 실현 할 수 있 습 니 다.

(function() {
 async function setAsyncTimeout(fn) {
  Promise.resolve().then(fn);
 }
 let i = 0;
 const start = Date.now();
 async function test() {
  if (i++ < 100) {
   await setAsyncTimeout(test);
  } else {
   console.log('setAsyncTimeout    :', Date.now() - start);
  }
 }
 setAsyncTimeout(test);
})();
setTimeout 버 전과 비교 한 결과 다음 과 같 습 니 다.
setAsyncTimeout 실행 시간:2
setTimeout 실행 시간:490
귀 찮 지 않 으 면 Promise 를 통 해 이 루어 질 수 있 습 니 다.사실은 모두 대동소이 합 니 다.코드 가 많 을 뿐만 아니 라 여 기 는 생략 합 니 다.
MessageChannel
Message Channel 은 새로운 메시지 채널 을 만 들 고 두 개의 Message Port 속성 을 통 해 데 이 터 를 보 낼 수 있 습 니 다.Message Channel 은 포트 개념 을 제공 하여 포트 간 의 통신 을 실현 합 니 다.예 를 들 어 worker/iframe 간 의 통신 등 입 니 다.

(function() {
 const channel = new MessageChannel();
 function setMessageChannelTimeout(fn) {
  channel.port2.postMessage(null);
 }
 channel.port1.onmessage = function() {
    test();
 };
 let i = 0;
 const start = Date.now();
 function test() {
  if(i++ < 100) {
   setMessageChannelTimeout(test);
  } else {
   console.log('setMessageChannelTimeout    :', Date.now() - start);
  }
 }
 setMessageChannelTimeout(test);
})();
setTimeout 버 전과 비교 한 결과 다음 과 같 습 니 다.
setMessageChannel 타임 아웃 실행 시간:4
setTimeout 실행 시간:490
세 번 째 방식 은 앞의 두 가지 방식 보다 운행 시간 이 더 길다.Message Channel 을 통 해 발생 하 는 것 은 매크로 임무 이 고 다른 두 가 지 는 마이크로 임무 이 며 마이크로 임 무 는 앞 에 있 고 메 인 스 레 드 를 막 기 때문에 시간 이 좀 길다.
마지막.
본 고 는 세 가지 실현 방식 을 제 공 했 는데 모두 js 가 비동기 해결 방안 을 제공 하 는 것 을 중심 으로 이 루어 진 것 으로 실현 자체 가 복잡 하지 않다.
부록
​​【1】 https://mp.weixin.qq.com/s/QRIXBoKr2dMgLob3Atq9-g
【2】 https://dbaron.org/log/20100309-faster-timeouts
【3】 https://dbaron.org/mozilla/zero-timeout
js 가 0 ms 지연 타 이 머 를 실현 하 는 몇 가지 방식 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 관련 js 지연 타 이 머 는 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 바 랍 니 다!

좋은 웹페이지 즐겨찾기