set Timeout(fn, 0)이 유용한 이유는 무엇입니까?
버그에 때, 그 는 「 i에에꽤꽤」, 「 i서 i i i i」를 로드하고 있었다.<select>
자바스크립트으로 로딩되었습니다.<select>
이치노된 IE6를 .<option>
「」가 되는 가 있기 때문입니다.<select>
의 »selectedIndex
한 값과 .<option>
의 »index
아트리뷰트
field.selectedIndex = element.index;
이치노밭이 너무 넓어서selectedIndex
올바르게 설정되어 있으면 잘못된 인덱스가 선택됩니다., 약약면면 면면 면면 면면 면면 면면 면면 면 면alert()
을 사용법타이밍의 문제일지도 모른다고 생각하고, 코드에서 본 적이 있는 랜덤한 것을 시험해 보았습니다.
var wrapFn = (function() {
var myField = field;
var myElement = element;
return function() {
myField.selectedIndex = myElement.index;
}
})();
setTimeout(wrapFn, 0);
그리고 이건 성공했어!
문제 해결 방법은 있지만, 왜 이것이 문제를 해결하는지 정확히 알 수가 없어요.식적인 해명 ?는 는?? ???나중에'을 '에' 할 수 입니까?setTimeout()
질문에서, 다음과 같은 경쟁 조건이 존재했습니다.
- 선택한 인덱스를 업데이트할 준비가 된 드롭다운 목록을 초기화하려는 브라우저의 시도입니다.
- 선택한 인덱스를 설정하기 위한 코드
당신의 코드는 이 레이스에서 계속 우승하여 브라우저가 준비되기 전에 드롭다운 선택을 설정하려고 했습니다.즉, 버그가 나타날 것입니다.
이 경주는 JavaScript가 페이지 렌더링과 공유되는 단일 실행 스레드를 가지고 있기 때문에 존재했습니다.실제로 JavaScript를 실행하면 DOM 업데이트가 차단됩니다.
회피책은 다음과 같습니다.
setTimeout(callback, 0)
를 호출하다setTimeout
콜백을 지정하고 두 번째 인수로 0을 지정하면 가능한 한 짧은 지연 후에 비동기적으로 콜백이 실행되도록 스케줄링됩니다.이것은 탭에 포커스가 있고 JavaScript 실행 스레드가 비지 상태일 때 약 10ms가 됩니다.
따라서 OP의 솔루션은 선택한 지수의 설정을 약 10ms 지연시키는 것이었다.이로 인해 브라우저는 DOM을 초기화하여 버그를 수정할 수 있게 되었습니다.
Internet Explorer의 모든 버전은 기발한 행동을 보였고 이러한 종류의 회피책이 필요할 때도 있었다.또는 OP 코드베이스의 정품 버그일 수도 있습니다.
자세한 설명은 Philip Roberts 토크 "What is the event loop?"을 참조하십시오.
서문:
그 외 정답은 맞지만 실제로 해결 중인 문제가 무엇인지 설명하지 못하고 있기 때문에 이 답변을 작성했습니다.
따라서 브라우저의 기능과 사용법에 대한 자세한 실사를 게시합니다.그것은 길쭉해 보이지만 사실은 매우 단순하고 직설적이다 - 나는 그것을 매우 상세하게 만들었을 뿐이다.
업데이트: 아래의 설명을 라이브로 확인하기 위해 JSFiddle을 만들었습니다.http://jsfiddle.net/C2YBE/31/. 킥스타트를 도와준 @ThangChung님 감사합니다.
업데이트 2: JSFiddle 웹사이트가 사망하거나 코드가 삭제될 경우를 대비해 마지막에 코드를 추가했습니다.
상세:
"do something" 버튼과 결과 div가 있는 웹 앱을 상상해 보십시오.
onClick
" something"하여 "do something"의 두 가지 작업을
매우 긴 계산(3분 소요)
계산 결과를 결과 div에 인쇄합니다.
이제 사용자가 테스트를 시작하고 "do something" 버튼을 클릭하면 페이지가 3분간 아무것도 하지 않는 것처럼 보입니다.또, 버튼을 클릭해, 1분간 대기해, 아무 일도 일어나지 않고, 버튼을 클릭해 주세요.
문제는 명백합니다.무슨 일이 일어나고 있는지를 나타내는 「Status(상태)」DIV가 필요합니다.어떻게 되는지 봅시다.
"Status비어 있음)를하고 "Status" DIV(상태)"를 변경합니다.onclick
함수)LongCalc()
4가지 작업:
상태를 채웁니다. "계산 중...상태 DIV까지 최대 3분 걸릴 수 있습니다.
매우 긴 계산(3분 소요)
계산 결과를 결과 div에 인쇄합니다.
"계산 완료" 상태를 상태 DIV에 채웁니다.
그리고 다시 테스트할 수 있는 앱을 사용자에게 제공합니다.
그들은 매우 화가 난 모습으로 당신에게 돌아옵니다.그리고 버튼을 클릭했을 때 상태 DIV가 "계산 중..."으로 업데이트되지 않았다고 설명합니다.상태!!!
머리를 긁적거리고 StackOverflow에 대해 물어보고(또는 문서를 읽거나 구글을 참조) 문제를 인식합니다.
브라우저는 이벤트에서 발생하는 모든 "TODO" 태스크(UI 태스크와 JavaScript 명령 모두)를 단일 큐에 넣습니다.그리고 안타깝게도 새로운 "계산 중"으로 "상태" DIV를 다시 그립니다." 값은 큐의 끝에 있는 개별 TODO입니다.
다음은 사용자 테스트 중 이벤트와 각 이벤트 후 큐의 내용 내역입니다.
- ★:
[Empty]
- 이벤트: 버튼을 클릭합니다.후 : " " " "
[Execute OnClick handler(lines 1-4)]
- 이벤트: OnClick 핸들러에서 첫 번째 줄을 실행합니다(예: 상태 DIV 값 변경).후 : " " " "
[Execute OnClick handler(lines 2-4), re-draw Status DIV with new "Calculating" value]
DOM 변경은 즉시 이루어지지만 대응하는 DOM 요소를 다시 그리려면 큐의 마지막에 DOM 변경으로 인해 트리거된 새로운 이벤트가 필요합니다. - 문제!!!문제!!!상세한 것에 대하여는, 이하를 참조해 주세요.
- 이벤트: 핸들러에서 두 번째 줄을 실행합니다(계산). 후:
[Execute OnClick handler(lines 3-4), re-draw Status DIV with "Calculating" value]
. - 이벤트: 핸들러에서 세 번째 줄을 실행합니다(결과 DIV 입력). 후:
[Execute OnClick handler(line 4), re-draw Status DIV with "Calculating" value, re-draw result DIV with result]
. - 이벤트: 핸들러에서 네 번째 줄을 실행합니다(상태 DIV에 "DONE"을 입력합니다).큐: ::
[Execute OnClick handler, re-draw Status DIV with "Calculating" value, re-draw result DIV with result; re-draw Status DIV with "DONE" value]
. - Event: execute implied 이벤트: 묵시적으로 실행
return
부에서onclick
핸들 하위러 브 we 서 " on and 들 핸 on the take ute executing)를 눌러 대기열에서 다음 항목을 실행할 수 있습니다.큐에서 "Execute OnClick 핸들러"를 삭제하고 큐에서 다음 항목의 실행을 시작합니다. - 메모: 계산은 이미 완료되었기 때문에 사용자는 이미 3분이 지났습니다.재추첨 이벤트는 아직 진행되지 않았습니다!!!
- 이벤트: "계산 중" 값으로 상태 DIV를 다시 그립니다.다시 그려서 큐에서 뺍니다.
- 이벤트: 결과 값을 사용하여 결과 DIV를 다시 그립니다.다시 그려서 큐에서 뺍니다.
- 이벤트: "Done" 값으로 상태 DIV를 다시 그립니다.다시 그려서 큐에서 뺍니다.날카로운 눈을 가진 시청자는 계산을 마친 후 "계산 중" 값이 마이크로초 동안 깜박이는 상태 DIV를 알아차릴 수도 있습니다.
따라서 근본적인 문제는 "Status" DIV의 다시 그리기 이벤트가 3분 걸리는 "execute line 2" 이벤트 후에 큐에 배치되기 때문에 실제 다시 그리기 작업은 계산이 완료될 때까지 실행되지 않는다는 것입니다.
To the rescue comes the 구조하러 온 것은setTimeout()
떻게게 도? ??를 경유하여 setTimeout
2개의 수 . , 2개의 이벤트를 만들겠습니다.setTimeout
실행 자체 및 (0 타임아웃으로 인해) 실행 중인 코드에 대한 개별 큐 엔트리를 지정합니다.
문제를 예요.onClick
가 TWO TWO 문 내의 이 되는 경우.onClick
상태를 채웁니다. "계산 중...상태 DIV까지 최대 3분 걸릴 수 있습니다.
타임아웃이 0이 되어 콜이 기능하도록 실행한다.
LongCalc()
함수는 지난 번과 거의 동일하지만 "계산 중..첫 단계로 후 합니다.
그럼 현재 이벤트시퀀스와 큐는 어떤 모습일까요?
- ★:
[Empty]
- 이벤트: 버튼을 클릭합니다.후 : " " " "
[Execute OnClick handler(status update, setTimeout() call)]
- 이벤트: OnClick 핸들러에서 첫 번째 줄을 실행합니다(예: 상태 DIV 값 변경).후 : " " " "
[Execute OnClick handler(which is a setTimeout call), re-draw Status DIV with new "Calculating" value]
- 시간 제한: 시간 제한 설정 후:
[re-draw Status DIV with "Calculating" value]
0으로 하다 - 이벤트: 타임아웃에 따른 알람이 0초 후에 울립니다. 후:
[re-draw Status DIV with "Calculating" value, execute LongCalc (lines 1-3)]
- 이벤트: "계산 중" 값으로 상태 DIV를 다시 그립니다.큐잉 시간:
[execute LongCalc (lines 1-3)]
이 재추첨 이벤트는 알람이 울리기 전에 실제로 발생할 수 있으므로 주의하시기 바랍니다. - ...
만세! 상태 DIV가 방금 "계산 중..계산 시작 전!!!
다음 예시는 JSFiddle의 샘플코드입니다.http://jsfiddle.net/C2YBE/31/
HTML 코드:
<table border=1>
<tr><td><button id='do'>Do long calc - bad status!</button></td>
<td><div id='status'>Not Calculating yet.</div></td>
</tr>
<tr><td><button id='do_ok'>Do long calc - good status!</button></td>
<td><div id='status_ok'>Not Calculating yet.</div></td>
</tr>
</table>
코드: (JavaScript에서 됨: (JavaScript에서 실행됨)onDomReady
1jQuery 1.9가 필요할 수 .)
function long_running(status_div) {
var result = 0;
// Use 1000/700/300 limits in Chrome,
// 300/100/100 in IE8,
// 1000/500/200 in FireFox
// I have no idea why identical runtimes fail on diff browsers.
for (var i = 0; i < 1000; i++) {
for (var j = 0; j < 700; j++) {
for (var k = 0; k < 300; k++) {
result = result + i + j + k;
}
}
}
$(status_div).text('calculation done');
}
// Assign events to buttons
$('#do').on('click', function () {
$('#status').text('calculating....');
long_running('#status');
});
$('#do_ok').on('click', function () {
$('#status_ok').text('calculating....');
// This works on IE8. Works in Chrome
// Does NOT work in FireFox 25 with timeout =0 or =1
// DOES work in FF if you change timeout from 0 to 500
window.setTimeout(function (){ long_running('#status_ok') }, 0);
});
JavaScript 타이머 작동 방법에 대한 John Resig의 기사를 참조하십시오.타임아웃을 설정하면 엔진이 현재 콜스택을 실행할 때까지 실제로는 비동기 코드를 큐잉합니다.
setTimeout()
벌 수 있습니다.는 0 . 、 0 、 0 、 0 、 DOM 、 DOM 、 DOM 、 DOM の buys buys buys buys buys buys buys buys buys buys buys buys buys buys buys buys buys 。
확인: set Timeout
브라우저에는 "메인 스레드"라고 불리는 프로세스가 있으며, 일부 JavaScript 태스크, UI 업데이트(예: 페인팅, 리드로, 리플로우 등)를 수행합니다.JavaScript 태스크는 메시지 큐에 큐잉된 후 브라우저의 메인 스레드로 디스패치되어 실행됩니다.메인 스레드가 사용 중일 때 UI 업데이트가 생성되면 작업이 메시지 대기열에 추가됩니다.
여기에는 상반된 답변들이 있고, 증거 없이는 누구를 믿어야 할지 알 길이 없다.다음은 @DVK가 옳고 @SalvadorDali가 틀렸다는 증거입니다.후자의 주장:
"그 이유는 다음과 같습니다.시간 지연이 0밀리초인 set Timeout은 불가능합니다.최소값은 브라우저에 의해 결정되며 0밀리초가 아닙니다.지금까지 브라우저에서는 최소 10밀리초로 설정되어 있었지만 HTML5 사양이나 최신 브라우저에서는 4밀리초로 설정되어 있습니다."
최소 4ms의 타임아웃은 현재 발생한 상황과 무관합니다.실제로 set Timeout은 콜백 함수를 실행 큐의 끝에 푸시합니다.setTimeout(콜백, 0) 후에 블로킹코드가 실행되는데 몇 초 걸리는 경우 콜백은 블로킹코드가 완료될 때까지 몇 초 동안 실행되지 않습니다.다음 코드를 사용해 보십시오.
function testSettimeout0 () {
var startTime = new Date().getTime()
console.log('setting timeout 0 callback at ' +sinceStart())
setTimeout(function(){
console.log('in timeout callback at ' +sinceStart())
}, 0)
console.log('starting blocking loop at ' +sinceStart())
while (sinceStart() < 3000) {
continue
}
console.log('blocking loop ended at ' +sinceStart())
return // functions below
function sinceStart () {
return new Date().getTime() - startTime
} // sinceStart
} // testSettimeout0
출력:
setting timeout 0 callback at 0
starting blocking loop at 5
blocking loop ended at 3000
in timeout callback at 3033
이렇게 하는 이유 중 하나는 별도의 후속 이벤트 루프에 대한 코드 실행을 연기하는 것입니다.브라우저 이벤트에 응답할 때(마우스 클릭 등) 현재 이벤트가 처리된 후에만 작업을 수행해야 하는 경우가 있습니다.그setTimeout()
가장 간단한 방법입니다.
2015년이니까 편집도 하고requestAnimationFrame()
setTimeout(fn, 0)
언급할 가치가 있다고 생각합니다.
이 두 가지 최고 등급의 답변은 모두 틀렸습니다.MDN의 설명을 동시성 모델과 이벤트루프에서 확인하시면 무슨 일이 일어나고 있는지 알 수 있습니다(MDN 리소스는 진정한 보석입니다).그리고 간단히 말하면 setTimeout
이 작은 문제를 해결하는 것 외에 코드에 예기치 않은 문제가 추가될 수 있습니다.
여기서 실제로 일어나고 있는 것은 "동시성이 있기 때문에 브라우저가 아직 충분히 준비되지 않았을 수 있다"거나 "각 행은 큐의 뒤에 추가되는 이벤트"에 기초한 것이 아닙니다.
DVK가 제공한 jsfiddle은 실제로 문제를 설명하지만, 그에 대한 그의 설명은 정확하지 않다.
있는하고 입니다.click
의 #do
버튼을 클릭합니다.
다음 실제로때, '버튼을 누르다'가 .message
핸들러 기능을 이 기능은 이벤트 핸들러 기능에 ★★★★★★★★★★★★★★★★★★,message queue
.event loop
하면, 「」가 됩니다.frame
fiddle의 합니다.
그리고 여기서부터 흥미로워집니다.우리는 Javascript가 비동기적이라고 생각하는 데 익숙해져 있기 때문에 이 작은 사실을 간과하기 쉽습니다.다음 프레임을 실행하기 전에 모든 프레임을 완전히 실행해야 합니다.동시성이 없다, 여러분.
이것은 무엇을 의미합니까?즉, 메시지 큐에서 함수가 호출될 때마다 생성되는 스택이 비워질 때까지 큐를 차단합니다.또는 일반적으로 함수가 반환될 때까지 차단합니다.또한 DOM 렌더링 작업, 스크롤 등의 모든 작업을 차단합니다.확인을 원할 경우, 바이올린에서 장시간 실행 작업을 계속(예: 외부 루프를 10회 더 실행)하면 실행 중에는 페이지를 스크롤할 수 없습니다.이 프로세스가 충분히 오래 실행되면 브라우저는 페이지가 응답하지 않게 되므로 프로세스를 종료할지 여부를 묻습니다.프레임이 실행되고 이벤트루프와 메시지큐가 완료될 때까지 정지합니다.
그런데 왜 텍스트의 부작용이 업데이트되지 않는 거죠?왜냐하면 DOM에서 요소의 값을 변경했을 때 - 할 수 있기 때문입니다.console.log()
변경 직후에 값이 변경되어 있는 것을 확인합니다(DVK의 설명이 올바르지 않은 이유를 알 수 있습니다).브라우저는 스택이 고갈될 때까지 대기하고 있습니다.on
반환하는 핸들러 함수)와 그에 따라 메시지가 종료되므로 변환 조작에 대한 반응으로 런타임에 의해 추가된 메시지를 실행할 수 있으며 UI에 변환이 반영됩니다.
이는 실제로 코드 실행이 완료될 때까지 대기하고 있기 때문입니다.이벤트 기반의 비동기 Javascript에서 보통 하는 것처럼 "누군가 이것을 가져와 결과를 가지고 함수를 호출합니다. 감사합니다. 이제 저는 끝났으니 돌아가겠습니다.무엇이든 지금 하세요"라고 말하지 않았습니다.클릭 이벤트 핸들러 함수에 들어가 DOM 요소를 갱신하고 다른 함수를 호출하고 다른 함수를 장시간 작동시킨 후 동일한 DOM 요소를 갱신하고 초기 함수에서 돌아와 스택을 효과적으로 비웁니다.그런 다음 브라우저는 큐 내의 다음 메시지로 이동할 수 있습니다.이것은 내부 "on-DOM-mutation" 유형의 이벤트를 트리거하여 생성된 메시지일 수 있습니다.
브라우저 UI는 현재 실행 중인 프레임이 완료될 때까지(함수가 반환될 때까지) UI를 업데이트할 수 없습니다.개인적으로 이것은 제약이라기보다 의도적인 것이라고 생각합니다.
?는 왜?setTimeout
럼럼효 ?과 ???프레임에서 입니다.window
컨텍스트를 지정하면 컨텍스트 자체가 즉시 반환되어 메시지 큐가 다른 메시지를 처리할 수 있습니다.즉, 우리가 Javascript에서 DOM의 텍스트를 변경할 때 트리거된 UI "on update" 메시지가 장기 실행 기능을 위해 큐잉된 메시지보다 앞서기 때문에 UI 업데이트가 장시간 차단되기 전에 발생한다는 것입니다.
a) 롱런 함수는 실행 시 모든 것을 차단하며, b) UI 업데이트가 실제로 메시지 큐에서 앞서 있음을 보증하지 않습니다.2018년 6월 Chrome 브라우저에서0
바이올린이 나타내는 문제를 '수정'할 수 없습니다.10은 해결합니다.UI 업데이트 메시지는 트리거가 "나중에" 실행되도록 스케줄링하기 전에 실행되므로 그 전에 큐에 넣어야 한다는 것이 논리적으로 이해하기 때문에 사실 조금 답답합니다.하지만 V8 엔진에 방해가 될 수 있는 몇 가지 최적화 기능이 있거나 제 이해가 부족할 수 있습니다.
'어느 정도'를 쓰면 죠?setTimeout
이우경 적합 ?합 ??? ???
「」, 「」의 .setTimeout
이러한 이벤트 핸들러에서는, 다른 문제를 경감하기 위해서, 다른 코드를 조작하는 경우가 있습니다.을 사용하다
에 대해 잘못 렌더링 중 하여 Javascript를 " 했습니다.setTimeout 0
그 렌더링에 대해서.그는 더 이상 질문하러 온 것이 아니지만, 아마도 렌더링 속도를 측정하기 위해 타이머를 삽입했을 것으로 추측됩니다(이것은 함수의 반환 즉시성). 이 방법을 사용하면 그 함수의 응답 속도가 엄청나게 빨라진다는 것을 알 수 있습니다.
첫 번째 문제는 명백합니다.javascript를 스레드할 수 없기 때문에 난독화를 추가하는 동안에는 아무것도 얻을 수 없습니다.다음으로 템플릿 렌더링을 이벤트청취자 스택에서 효과적으로 분리할 수 있습니다.이러한 이벤트청취자 스택은 템플릿 렌더링을 하지 않았을 가능성이 있습니다.그 함수의 실제 동작은 그것을 실행하거나 그것에 의존하는 함수와 마찬가지로 결정적이지 않게 되었습니다.교묘한 추측은 할 수 있지만, 그 행동을 적절히 코드화할 수는 없습니다.
새로운 이벤트 핸들러를 작성할 때 그 논리에 의존한 "수정"은 또한setTimeout 0
그러나 그것은 수정이 아니라 이해하기 어렵고, 이러한 코드로 인해 발생한 오류를 디버깅하는 것은 재미가 없습니다.문제가 전혀 없을 때도 있고 지속적으로 장애가 발생할 때도 있으며, 플랫폼의 현재 성능이나 그 시점에 어떤 일이 일어나는지에 따라 때때로 작동하거나 중단될 수도 있습니다.그렇기 때문에 저는 개인적으로 이 해킹을 사용하지 말 것을 권합니다(해킹이며, 우리는 모두 알고 있어야 합니다). 만약 당신이 무엇을 하고 있는지, 그리고 그 결과가 무엇인지 정말로 알지 못한다면 말입니다.
하지만 우리가 뭘 할 수 있을까요?참조된 MDN 문서에서 제시된 바와 같이 작업을 여러 메시지로 분할하여 큐잉된 다른 메시지를 작업과 인터리브하여 실행할 수 있도록 하거나 웹 워커를 사용합니다.웹 워커는 페이지와 동시에 실행되며 계산 완료 시 결과를 반환합니다.
아, 그리고 '비동기적으로 하기 위해 콜백을 롱런 함수에 넣으면 안 될까요?'라고 생각하시면 안 됩니다.콜백은 비동기화가 되지 않습니다.콜백을 명시적으로 호출하기 전에 장기 실행 코드를 실행해야 합니다.
이것은 해답이 있는 오래된 질문이다.이 문제에 대해 새로운 관점을 추가하고 이것이 왜 도움이 되는지가 아니라 왜 이런 일이 일어나는지 답변하고 싶었습니다.
두 가지 기능이 있습니다.
var f1 = function () {
setTimeout(function(){
console.log("f1", "First function call...");
}, 0);
};
var f2 = function () {
console.log("f2", "Second call...");
};
대로 불러주세요.f1(); f2();
두 번째 사람이 먼저 처형되는 걸 보기 위해서요
그리고 여기 그 이유가 있다: 그 이유는setTimeout
0밀리초의 시간 지연을 수반합니다.최소값은 브라우저에 의해 결정되며 0밀리초가 아닙니다.지금까지 브라우저에서는 최소 10밀리초로 설정되어 있었지만 HTML5 사양과 최신 브라우저에서는 4밀리초로 설정되어 있습니다.
네스트 레벨이 5보다 크고 타임아웃이 4보다 작을 경우 타임아웃을 4로 늘립니다.
또한 Mozilla에서:
최신 브라우저에서 0 ms의 타임아웃을 구현하려면 window.post Message()를 사용합니다.
P.S. 정보는 다음 기사를 읽고 얻은 것입니다.
전체 비디오를 보고 싶지 않은 경우, 이 질문에 대한 답변을 이해하기 위해 알아야 할 사항에 대한 간단한 설명을 다음에 제시하겠습니다.
- JavaScript는 싱글 스레드이므로 실행할 때 한 번에 한 가지 작업만 수행합니다.
- 그러나 JavaScript가 실행되고 있는 환경은 멀티 스레드화가 가능합니다.예를 들어 브라우저는 멀티 스레드 생물인 경우가 많습니다. 즉, 한 번에 여러 가지 작업을 수행할 수 있습니다.따라서 JavaScript를 실행하는 동시에 다른 작업도 추적할 수 있습니다.
자바스크립트★★★★★★★★★★★★★★★★★★★ 등setTimeout
JavaScript를 사용합니다.
- JavaScript를 비동기적으로 실행할 수 있는 것은 멀티 스레드 브라우저입니다!Javascript가 사용하는 메인 공간(콜 스택이라고 함) 외에 브라우저는 JavaScript에 물건을 놓을 수 있는 다른 공간도 제공합니다.
이제 다른 공간을 두 번째 공간이라고 부릅시다.
- 를 들어, 정해 let let let let let let let let let
fn
함수입니다.여기서 이해해야 할 중요한 점은 콜이 콜과 동일하지 않다는 것입니다.이것에 대해서는, 이하에 자세하게 설명합니다.
0
예를 들어 먼저 해 보겠습니다.를 들어, 5000밀리초의 지연이 경우, 5000밀리초의 지연이 발생합니다.setTimeout(fn, 5000);
중요한 것은, 이것은 아직 「함수 호출」이기 때문에, 메인 스페이스에 배치해 두고, 완료하면 떼어낼 필요가 있습니다만, 기다려 주세요.지루하고 지루한 5초의 지연은 별로입니다.그러면 메인 공간이 차단되고 자바스크립트가 그 사이에 다른 어떤 것도 실행할 수 없게 됩니다.
다행히 브라우저 설계자가 설계한 방식은 아닙니다.대신 이 call()setTimeout(fn, 5000);
은 즉시 실행됩니다. 이것은 매우 중요합니다. 5000밀리초의 지연이 있어도 이 함수 호출은 순식간에 완료됩니다.다음에 무슨 일이 일어날까?메인 스페이스에서 제외됩니다.어디에 두게 될까요? (잃어버리고 싶지 않기 때문에)짐작하신 대로입니다.브라우저는 이 콜을 듣고 두 번째 공간에 배치합니다.
브라우저는 5초 지연을 추적하여 이 지연이 지나면 메인 공간을 보고 "WHEN IT'S EMPTY"는 콜을 다시 전송합니다.이렇게 해서setTimeout
그럼 ,, 시, 시 시 시 시 시 시 시 시 시 。setTimeout(fn, 0)
지연이 제로가 되어도 이것은 브라우저에 대한 콜입니다.브라우저는 즉시 이 콜을 듣고 그것을 픽업하여 메인공간이 다시 비었을 때만 두 번째 공간에 놓고 메인공간으로 되돌립니다(0밀리초 후가 아닙니다).
설명도 잘 해주시고 기술적인 것도 더 많이 열어주시니까 그 영상도 꼭 보시길 권해드립니다.
에, 지속 은 「」입니다.0
에 전달된 코드를 삭제하기 위해서라고 생각합니다.setTimeout
행행의실따라서 시간이 걸릴 수 있는 함수라면 후속 코드 실행을 방해하지 않습니다.
또, 함수의 호출을 스택의 하부에 푸시 하는 것으로, 함수를 재귀적으로 호출하는 경우에 스택의 오버플로를 방지합니다. 하면 이은은 of of of of of of의 효과가 .while
자바스크립트
set Timeout을 호출하면 사용자가 무엇을 하고 있는지 페이지에 응답할 시간이 주어집니다.이것은 특히 페이지 로드 중에 실행되는 기능에 도움이 됩니다.
set Timeout 이 도움이 되는 다른 경우:
장기간 실행되는 루프 또는 계산을 더 작은 구성요소로 분할하여 브라우저가 '고정'되거나 "페이지에 있는 스크립트가 사용 중"으로 표시되지 않도록 할 수 있습니다.
클릭했을 때 폼 송신 버튼을 무효로 하고 싶지만 onClick 핸들러에서 폼을 무효로 하면 폼이 송신되지 않습니다.시간이 0인 set Timeout이 유효하게 되어 이벤트가 종료되고 폼이 송신되기 시작하면 버튼을 무효로 할 수 있습니다.
문제는 존재하지 않는 요소에 대해 Javascript 작업을 수행하려고 했다는 것입니다.는 아직 되지 않았고 소소 the the the the the the the the the the the the the the the the the the the the the the the.setTimeout()
까지 더 많은 합니다.
setTimeout()
이벤트는 비동기적이므로 모든 동기 코드 후에 실행되므로 요소를 로드할 시간이 길어집니다.의 콜백과 같은 비동기 콜백setTimeout()
는 이벤트 큐에 배치되어 동기 코드 스택이 비면 이벤트루프에 의해 스택에 배치됩니다.- " " " 의 두 번째 의 값0 은 " " " ms " 입니다.
setTimeout()
(브라우저에 따라 4~10밀리초)가 약간 높은 경우가 많습니다. 은 " " " " 를 하기 위해 더 .setTimeout()
콜백은 이벤트루프의 '콜백'(스택이 비어 있는 경우 틱이 스택의 콜백을 푸시하는 경우)의 양에 의해 발생합니다.성능 및 배터리 지속 시간 때문에 이벤트 루프의 틱 수는 초당 1000회 미만으로 제한됩니다.
실행 루프와 다른 코드가 완료되기 전에 DOM을 렌더링하는 것에 대한 답변은 정확합니다.JavaScript의 제로초 타임아웃은 코드가 유사 멀티스레드가 아닌 경우에도 도움이 됩니다.
많은 모바일 브라우저가 AMD 칩의 클럭 제한으로 인해 20밀리초 미만의 타임아웃을 등록할 수 없기 때문에 JavaScript의 크로스 브라우저/크로스 플랫폼0초 타임아웃의 BEST 값은 실제로는 0이 아니라 약 20밀리초입니다.
또한 DOM 조작을 수반하지 않는 장기 실행 프로세스는 JavaScript의 진정한 멀티스레드 실행을 제공하기 때문에 웹 워커에게 전송해야 합니다.
setTimeout on 0 은 지연된 약속을 설정하는 패턴에서도 매우 편리합니다.이러한 약속은 즉시 반환됩니다.
myObject.prototype.myMethodDeferred = function() {
var deferredObject = $.Deferred();
var that = this; // Because setTimeout won't work right with this
setTimeout(function() {
return myMethodActualWork.call(that, deferredObject);
}, 0);
return deferredObject.promise();
}
//When need "new a", setTimeout(fn, 0) is useful, when need to wait some action. Example:
var a = function (){console.log('a');};
var b = function(){setTimeout(b, 100);}; //wait some action before override this function
//without setTimeout:
console.log('no setTimeout: b.toString():', b.toString());
b(); //"b" is an old function
console.log('no setTieout: a.toString(): ', a.toString());
a(); //and "a" is not overrided
setTimeout(//but with setTimeout(fn, 0):
function(){
console.log('After timeout 0, b.toString(): ', b.toString());
b(); //"b" is a new function
console.log('After timeout 0, a.toString(): ', a.toString());
a(); //and "a" is overrided
},
0
);
//override var "b", which was been undefined
b = function (){
a = function(){console.log('new a');};
}
Javascript는 싱글 스레드 어플리케이션이기 때문에 이 이벤트 루프를 달성하기 위해 기능을 동시에 실행할 수 없습니다.따라서 set Timeout(fn, 0)이 수행하는 작업은 콜스택이 비어 있을 때 실행되는 태스크 퀘스트에 푸시됩니다.이 설명은 매우 지루하다는 것을 알고 있으므로 이 비디오를 통해 브라우저의 후드 아래에서 작업을 수행하는 데 도움이 될 것입니다.이 비디오를 확인해 주세요.- https://www.youtube.com/watch?time_continue=392&v=8aGhZQkoFbQ
언급URL : https://stackoverflow.com/questions/779379/why-is-settimeoutfn-0-sometimes-useful
'source' 카테고리의 다른 글
데이터베이스 가져오기 오류 구문 (0) | 2023.02.01 |
---|---|
PHP sprintf 이스케이프 % (0) | 2023.02.01 |
범례를 줄거리 외부에 배치하는 방법 (0) | 2023.02.01 |
PHP에서 HTTP 메서드 알아보기 (0) | 2023.02.01 |
MySQL 데이터베이스에서 버전 제어(Git) 사용 (0) | 2023.02.01 |