NodeJS-setTimeout (fn, 0) 대 setImmediate (fn)


답변:


72

setTimeout 은 단순히 지연이 완료된 후 함수를 호출하는 것과 같습니다. 함수가 호출 될 때마다 즉시 실행되지 않고 모든 실행 및 현재 대기중인 이벤트 핸들러가 먼저 완료된 후에 실행되도록 대기됩니다. setTimeout (, 0)은 본질적으로 현재 큐의 모든 현재 함수가 실행 된 후 실행됨을 의미합니다. 시간이 얼마나 걸릴지 보장 할 수 없습니다.

setImmediate 는 함수 대기열을 사용하지 않는다는 점을 제외하면 이와 유사합니다. I / O 이벤트 핸들러의 큐를 확인합니다. 현재 스냅 샷의 모든 I / O 이벤트가 처리되면 콜백을 실행합니다. process.nextTick과 비슷하게 마지막 I / O 핸들러 바로 뒤에 큐에 넣습니다. 그래서 더 빠릅니다.

또한 (setTimeout, 0)은 실행하기 전에 적어도 한 번 타이머를 확인하므로 느려집니다. 때로는 두 배로 느려질 수 있습니다. 다음은 벤치 마크입니다.

var Suite = require('benchmark').Suite
var fs = require('fs')

var suite = new Suite

suite.add('deffered.resolve()', function(deferred) {
  deferred.resolve()
}, {defer: true})

suite.add('setImmediate()', function(deferred) {
  setImmediate(function() {
    deferred.resolve()
  })
}, {defer: true})

suite.add('setTimeout(,0)', function(deferred) {
  setTimeout(function() {
    deferred.resolve()
  },0)
}, {defer: true})

suite
.on('cycle', function(event) {
  console.log(String(event.target));
})
.on('complete', function() {
  console.log('Fastest is ' + this.filter('fastest').pluck('name'));
})
.run({async: true})

산출

deffered.resolve() x 993 ops/sec ±0.67% (22 runs sampled)
setImmediate() x 914 ops/sec ±2.48% (57 runs sampled)
setTimeout(,0) x 445 ops/sec ±2.79% (82 runs sampled)

첫 번째는 가능한 가장 빠른 통화에 대한 아이디어를 제공합니다. setTimeout이 다른 것보다 절반으로 호출되는지 직접 확인할 수 있습니다. 또한 setImmediate는 파일 시스템 호출에 맞게 조정됩니다. 따라서 부하가 걸리면 성능이 떨어집니다. 나는 setTimeout이 더 잘 할 수 있다고 생각하지 않습니다.

setTimeout은 잠시 후 함수를 호출하는 방해가되지 않는 방법입니다. 브라우저에서와 똑같습니다. 서버 측에는 적합하지 않을 수 있습니다 (setTimeout이 아닌 benchmark.js를 사용한 이유를 생각해보십시오).


3
setTimeout은 5 번 중첩 된 경우 최소 4 밀리 초의 강제 지연이 적용된다는 점에 유의해야합니다. html 사양 참조
Jack Allan

(다른 답변에서)이 소스는 여기에 문장의 일부를 반박하는 것 같다 voidcanvas.com/setimmediate-vs-nexttick-vs-settimeout
드미트리 Zaitsev

17

이벤트 루프의 작동 방식에 대한 훌륭한 기사이며 오해를 해소합니다. http://voidcanvas.com/setimmediate-vs-nexttick-vs-settimeout/

기사 인용 :

setImmediateI / O 대기열 콜백이 완료되거나 시간 초과 된 후에 콜백이 호출됩니다. setImmediate 콜백은 I / O Queue 이후에 처리되는 Check Queue에 배치됩니다.

setTimeout(fn, 0)콜백은 Timer Queue에 배치되며 I / O 콜백과 Check Queue 콜백 후에 호출됩니다. 이벤트 루프로 각 반복에서 먼저 타이머 큐를 처리하므로 어느 것이 먼저 실행 될지는 위상 이벤트 루프가 무엇인지에 따라 달라집니다.


setTimeout 대기열은 I / O 콜백 전에 처리됩니다. ref : nodejs.org/en/docs/guides/event-loop-timers-and-nexttick
인간

5

setImmediate () 는 I / O 이벤트 콜백 후 setTimeout 및 setInterval 이전에 콜백의 즉각적인 실행을 예약하는 것입니다.

setTimeout () 은 지연 밀리 초 후에 일회성 콜백 실행을 예약하는 것입니다.

이것은 문서가 말하는 것입니다.

setTimeout(function() {
  console.log('setTimeout')
}, 0)

setImmediate(function() {
  console.log('setImmediate')
})

위의 코드를 실행하면 결과는 다음과 같습니다. 현재 문서에 "I / O 이벤트 콜백 후, setTimeout 및 setInterval 이전에 콜백의"즉시 "실행을 예약하려면"이라고 명시되어 있지만. ..

결과..

setTimeout

setImmediate

예제를 다른 타이머로 래핑하면 항상 setImmediate 다음에 setTimeout이 인쇄됩니다.

setTimeout(function() {
  setTimeout(function() {
    console.log('setTimeout')
  }, 0);
  setImmediate(function() {
    console.log('setImmediate')
  });
}, 10);

그렇다면 언제 다른 것을 선호합니까?
Shlomi Schwartz

23
당신이 보여준 일이 왜 일어나는지 설명하지 않았습니다. 이 대답은 나에게 유용하지 않았습니다.
Clint Eastwood 2015

3
에서는 setTimeout을 setImmediate하기 전에 먼저 실행하는 이유 @Savannah 첫 번째 결과에서 설명해주십시오
아구스 Syahputra에게


1
SetImmediate은의 setTimeout과 setInterval을 항상 전에 실행 실 거예요
Midhun GS

2

setImmediate당신이 정말로 필요하다고 확신하지 않는 한 항상를 사용 하십시오 setTimeout(,0)(그러나 나는 상상조차 할 수 없습니다, 무엇을 위해). setImmediate콜백은 setTimeout(,0)첫 번째 틱 및 setImmediate콜백 에서 호출되는 경우를 제외하고 거의 항상 이전 에 실행 됩니다 .


1
setImmediate 대신 setTimeout을 사용하는 주된 이유는 setImmediate가 구현되지 않은 브라우저에서 코드를 실행해야하기 때문입니다. 그래도 심을 만들 수 있습니다.
Gregory Magarshak

9
이것은 불건전 한 조언입니다. 모든 것이 먼저 진행되도록 요구하면 비동기 실행의 새로운 성능 특성이 마지막 대기열에 비해 쓰레기가 될 것입니다. setTimeout와, 이동-에 있어야합니다 setImmediate필요하다고 표시된 경우에만 사용.
Rich Remer

1

제공된 답변에 완전히 만족하지 않습니다. 더 나은 답변이라고 생각하는 내용을 여기에 게시했습니다. https://stackoverflow.com/a/56724489/5992714

질문은 주 모듈에서 사용할 때 setTimeout (0) 및 setImmediate ()의 동작이 정의되지 않은 이유는 무엇입니까?


1
두 가지 질문에 정확히 같은 답변을 게시하지 마십시오. 질문이 다른 경우 각각에 대한 답변을 조정하십시오. 동일한 경우 플래그를 지정하거나 투표하여 중복 항목을 닫으십시오.
Tom Zych 19

@TomZych가 언급했습니다.
human

0

Navya S 의 대답이 올바르지 않다고 생각합니다 . 여기에 내 테스트 코드가 있습니다.

let set = new Set();

function orderTest() {
  let seq = [];
  let add = () => set.add(seq.join());
  setTimeout(function () {
    setTimeout(function () {
      seq.push('setTimeout');
      if (seq.length === 2) add();
    }, 0);

    setImmediate(function () {
      seq.push('setImmediate');
      if (seq.length === 2) add();
    });
  }, 10);
}

// loop 100 times
for (let i = 0; i < 100; i++) {
  orderTest();
}

setTimeout(() => {
  // will print one or two items, it's random
  for (item of set) {
    console.log(item);
  }
}, 100);

설명은 여기


0

setTimeout (fn, 0)은 대규모 업데이트에서 브라우저가 중단되는 것을 방지하는 데 사용할 수 있습니다. 예를 들어 websocket.onmessage에서 html 변경이있을 수 있으며 메시지가 계속 오면 setImmidiate를 사용할 때 브라우저가 멈출 수 있습니다.


0

그것들을 깊이 이해하려면 이벤트 루프 단계를 한 번 살펴보십시오.

SetImmediate : "확인"단계에서 실행됩니다. 체크 단계는 I / O 단계 이후라고합니다.

SetTimeOut : "타이머"단계에서 실행됩니다. 타이머 단계는 첫 번째 단계이지만 한 후 호출 할 I / O의 단계뿐만 아니라 확인 단계입니다.

결정적인 방식으로 출력을 얻으려면 이벤트 루프가 어느 단계인지에 따라 달라집니다. 따라서 우리는 두 가지 기능을 사용할 수 있습니다.


-5

이벤트 루프를 차단하지 않으려면 setImmediate ()를 사용하십시오. 콜백은 현재 이벤트가 완료되는 즉시 다음 이벤트 루프에서 실행됩니다.

지연을 제어하려면 setTimeout ()을 사용하십시오. 이 기능은 지정된 지연 후에 실행됩니다. 최소 지연은 1 밀리 초입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.