문제

나는 최근에 코드가 <select> JavaScript를 통해 동적으로. 이 동적으로로드되었습니다 <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가 종종 사용되는 것 중 하나는 브라우저에 디스플레이 요소를 작성하도록 요청하는 것입니다. 이것은 종종 동기식으로 수행되는 것으로 가정하지만 (특히 JavaScript가 병렬로 실행되지 않기 때문에) 이것이 사실이라는 보장은 없으며 JavaScript에는 잘 정의 된 대기 메커니즘이 없습니다.

해결책은 렌더링 스레드를 따라 잡을 수 있도록 JavaScript 실행을 "일시 중지"하는 것입니다. 그리고 이것이 효과입니다 setTimeout() 타임 아웃과 함께 0 하다. 그것은 C의 스레드/프로세스 수율과 같습니다. 비록 "즉시 실행"이라고 말하는 것처럼 보이지만 실제로 브라우저는이 새로운 JavaScript에 참석하기 전에 끝나기 전에 기다리고 있던 비 자바 스크립트 작업을 완료 할 수있는 기회를 제공합니다. .

(실제로, setTimeout() 실행 큐의 끝에서 새 JavaScript를 다시 확인합니다. 더 긴 설명에 대한 링크에 대한 의견을 참조하십시오.)

IE6은이 오류가 발생하기 쉬운 일이지만, 이전 버전의 Mozilla와 Firefox에서 발생하는 것을 보았습니다.


Philip Roberts Talk를 참조하십시오 "이벤트 루프는 무엇입니까?" 더 철저한 설명을 위해.

다른 팁

머리말:

중요한 참고 사항 : 가장 활발하고 받아 들여지는 반면 @staticsan의 수락 된 답변은 실제로 정확하지 않습니다! - 이유에 대해서는 David Mulder의 의견을 참조하십시오.

다른 답변 중 일부는 정확하지만 실제로 해결되는 문제가 무엇인지 설명하지 않으므로이 답을 만들기 위해이 답을 만들었습니다.

따라서 나는 a를 게시하고있다 브라우저가하는 일과 사용 방법에 대한 상세한 연습 setTimeout() 도움이됩니다. 그것은 길게 보이지만 실제로는 매우 간단하고 간단합니다 - 나는 그것을 매우 상세하게 만들었습니다.

업데이트: 나는 아래의 설명을 생생하게 만들기 위해 jsfiddle을 만들었습니다. http://jsfiddle.net/c2ybe/31/ . 많은 감사해요 킥 스타트를 돕는 @thangchung에게.

Update2 : JSFIDDLE 웹 사이트가 사망하거나 코드를 삭제하는 경우이 답변에 코드를 추가했습니다.


세부:

"Do Do"버튼과 결과 Div가있는 웹 앱을 상상해보십시오.

그만큼 onClick "Something Do"버튼을위한 핸들러는 함수를 "longcalc ()"라고 부릅니다.

  1. 매우 긴 계산을 만듭니다 (예 : 3 분)

  2. 계산 결과를 결과 Div로 인쇄합니다.

이제 사용자 가이 테스트를 시작하고 "뭔가"버튼을 클릭하고 페이지가 3 분 동안 겉보기에 아무것도하지 않고, 불안해, 다시 버튼을 클릭하고, 1 분 동안 기다리지 않고, 아무것도 일어나지 않고 다시 버튼을 클릭하십시오 ... 다시 클릭하십시오 ...

문제는 분명합니다 - 당신은 "상태"div를 원합니다. 그것이 어떻게 작동하는지 봅시다.


그래서 당신은 "상태"div (처음에 비어 있음)를 추가하고 수정합니다. onclick 핸들러 (기능 LongCalc()) 4 가지 작업 :

  1. "계산 ... ~ 3 분이 걸릴 수있다"는 상태를 채우십시오.

  2. 매우 긴 계산을 만듭니다 (예 : 3 분)

  3. 계산 결과를 결과 Div로 인쇄합니다.

  4. "계산 완료"상태를 상태 div로 채우는 상태

그리고 당신은 행복하게 앱을 사용자에게 다시 테스트 할 수 있도록 앱을 제공합니다.

그들은 당신에게 매우 화가났습니다. 그리고 그들이 버튼을 클릭했을 때, 상태 div는 "계산"상태로 업데이트되지 않았습니다!


머리를 긁고 stackoverflow (또는 문서 또는 Google을 읽음)를 물어보고 문제를 깨닫습니다.

브라우저는 이벤트에서 이벤트로 인한 모든 "TODO"작업 (UI 작업 및 JavaScript 명령)을 단일 대기열. 불행히도, 새로운 "계산"과 함께 "상태"div를 다시 주도하는 ... 값은 큐의 끝으로가는 별도의 할 일입니다!

다음은 사용자 테스트 중 이벤트가 각 이벤트 후 대기열의 내용을 분석합니다.

  • 대기줄: [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].
  • 이벤트 : 핸들러에서 3 번째 라인을 실행합니다 (추적 결과 div). 큐 이후 : [Execute OnClick handler(line 4), re-draw Status DIV with "Calculating" value, re-draw result DIV with result].
  • 이벤트 : 핸들러에서 4 번째 라인을 실행합니다 ( "완료된"상태 div를 채우십시오). 대기줄: [Execute OnClick handler, re-draw Status DIV with "Calculating" value, re-draw result DIV with result; re-draw Status DIV with "DONE" value].
  • 이벤트 : 묵시적 실행 return ~에서 onclick 핸들러 서브. "Onclick Handler"를 대기열에서 제거하고 큐에서 다음 항목을 실행하기 시작합니다.
  • 참고 : 이미 계산을 마쳤으므로 3 분이 이미 사용자를 위해 통과되었습니다. 다시 드로프 이벤트는 아직 일어나지 않았습니다 !!!
  • 이벤트 : "계산"값으로 상태 div를 다시 드로프합니다. 우리는 다시 드로프하고 대기열에서 벗어납니다.
  • 이벤트 : 결과 값이있는 결과 DIV를 다시 드로프합니다. 우리는 다시 드로프하고 대기열에서 벗어납니다.
  • 이벤트 : "완료"값을 가진 상태 div를 다시 드로프합니다. 우리는 다시 드로프하고 대기열에서 벗어납니다. 날카로운 시청자들도 마이크로 초의 일부에 대해 "계산"값이 깜박 거리는 "상태 div"를 발견 할 수도 있습니다. 계산이 완료된 후

따라서 근본적인 문제는 "상태"DIV에 대한 재 드로프 이벤트가 3 분이 걸리는 "Line 2"이벤트가 끝난 후 끝에 큐에 배치되므로 실제 다시 드로우가 발생하지 않아야한다는 것입니다. 계산이 완료된 후.


구조대에 온다 setTimeout(). 어떻게 도움이됩니까? 장기 실행 코드를 통해 setTimeout, 당신은 실제로 두 가지 이벤트를 만듭니다. setTimeout 실행 자체 및 (타임 아웃으로 인해) 실행중인 코드에 대한 별도의 대기열 항목.

따라서 문제를 해결하기 위해 onClick 두 개의 진술이 될 핸들러 (새 기능 또는 내부의 블록 만 onClick):

  1. "계산 ... ~ 3 분이 걸릴 수있다"는 상태를 채우십시오.

  2. 실행하다 setTimeout() 0 타임 아웃과 전화로 LongCalc() 기능.

    LongCalc() 기능은 지난 시간과 거의 동일하지만 분명히 "Calculating ..."상태 DIV 업데이트는 첫 번째 단계입니다. 대신 계산을 즉시 시작합니다.

그렇다면 이벤트 시퀀스와 대기열은 현재 어떻게 생겼습니까?

  • 대기줄: [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].
  • 이벤트 : 핸들러에서 두 번째 줄을 실행합니다 (Settimeout Call). 큐 이후 : [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 코드 : (실행되었습니다 onDomReady jQuery 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);
});

John Resig의 기사에 대한 기사를 살펴보십시오 JavaScript 타이머의 작동 방식. 타임 아웃을 설정하면 엔진이 현재 통화 스택을 실행할 때까지 비동기 코드를 실제로 대기합니다.

setTimeout() 0으로 설정 되더라도 DOM 요소가로드 될 때까지 시간을 구입합니다.

이것 좀 봐: 설정 타임 아웃

대부분의 브라우저는 메인 스레드라는 프로세스가 있으며, 일부 JavaScript 작업, UI 업데이트 (그림, Redraw 또는 Reflow 등)를 실행할 책임이 있습니다.

일부 JavaScript 실행 및 UI 업데이트 작업이 브라우저 메시지 큐에 대기되어있는 다음 브라우저 기본 스레드로 발송됩니다.

기본 스레드가 바쁘면 UI 업데이트가 생성되면 작업이 메시지 큐에 추가됩니다.

setTimeout(fn, 0); 이거 추가 해봐 fn 대기열의 끝까지 실행됩니다. 주어진 시간 후에 메시지 대기열에 작업을 추가 할 예정입니다.

여기에는 상충되는 답변이 있으며, 증거가 없으면 누구를 믿어야할지 알 수있는 방법이 없습니다. 다음은 @dvk가 옳고 @salvadordali가 잘못되었다는 증거입니다. 후자의 주장 :

"여기에 이유가 있습니다 : 시간 지연이 0 밀리 초의 설정 타임 아웃을 할 수는 없습니다. 최소값은 브라우저에 의해 결정되며 0 밀리 초가 아닙니다. 역사적으로 브라우저는이 최소값을 10 밀리 초로 설정하지만 HTML5 사양과 HTML5 사양과 10 밀리 초. 최신 브라우저에는 4 밀리 초로 설정되어 있습니다. "

4ms 최소 시간 초과는 일어나는 일과 관련이 없습니다. 실제로 발생하는 것은 Settimeout이 콜백 함수를 실행 큐의 끝까지 푸시한다는 것입니다. 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) 언급 할 가치가 있습니다.

이것은 오래된 답변이있는 오래된 질문입니다. 이 문제에 대한 새로운 모습을 추가하고 왜 이런 일이 발생하는지에 대한 대답을하고 싶었습니다.

따라서 두 가지 기능이 있습니다.

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에서 :

최신 브라우저에서 0ms 타임 아웃을 구현하려면 설명대로 Window.PostMessage ()를 사용할 수 있습니다. 여기.

PS 정보는 다음을 읽은 후에 수행됩니다 기사.

기간이 지났기 때문에 0, 나는 그것이 전달 된 코드를 제거하기 위해 setTimeout 실행 흐름에서. 따라서 시간이 걸릴 수있는 기능이라면 후속 코드가 실행되는 것을 방해하지 않습니다.

이 두 가지 최고급 답변은 모두 잘못되었습니다. 동시성 모델 및 이벤트 루프에서 MDN 설명을 확인하십시오., 그리고 무슨 일이 일어나고 있는지 분명해야합니다 (MDN 자원은 실제 보석 임). 그리고 간단히 사용합니다 setTimeout 이 작은 문제를 "해결"하는 것 외에도 코드에 예기치 않은 문제를 추가 할 수 있습니다.

뭐야 실제로 여기서 진행되는 것은 "동시성이 아직 준비되지 않았을 수도 있습니다"또는 "각 라인을 기반으로하는 것은"각 줄은 대기열 뒷면에 추가되는 이벤트 "가 아닙니다.

그만큼 jsfiddle DVK가 제공하는 것은 실제로 문제를 보여 주지만 그의 설명은 정확하지 않습니다.

그의 코드에서 일어나는 일은 그가 이벤트 핸들러를 처음에 첨부하고 있다는 것입니다. click 이벤트 #do 단추.

그런 다음 실제로 버튼을 클릭하면 message 이벤트 핸들러 기능을 참조하여 message queue. 때 event loop 이 메시지에 도달하면 a를 만듭니다 frame 스택에서 JSFIDDLE의 클릭 이벤트 핸들러에 대한 기능 호출.

그리고 이것이 흥미로워지는 곳입니다. 우리는 JavaScript를 비동기식으로 생각하는 데 익숙해 져서 우리는이 작은 사실을 간과하기 쉽습니다. 다음 프레임을 실행하기 전에 모든 프레임을 전체적으로 실행해야합니다.. 동시성 없음, 사람들.

이것은 무엇을 의미 하는가? 그것은 메시지 큐에서 함수가 호출 될 때마다 생성 된 스택이 비워 질 때까지 큐를 차단한다는 것을 의미합니다. 또는보다 일반적인 용어로는 함수가 돌아올 때까지 차단됩니다. 그리고 그것은 차단됩니다 모든 것, Dom 렌더링 작업, 스크롤 및 What Not을 포함하여. 확인을 원한다면 바이올린에서 장기 실행 작업 기간을 늘리면 (예 : 외부 루프를 10 번 더 실행) 실행 중에는 페이지를 스크롤 할 수 없음을 알 수 있습니다. 충분히 길게 실행되면 브라우저는 페이지를 반응하지 않기 때문에 프로세스를 죽이고 싶은지 묻습니다. 프레임이 실행되고 이벤트 루프 및 메시지 큐가 완료 될 때까지 붙어 있습니다.

그렇다면 왜 텍스트가 업데이트되지 않는가? 당신이있는 동안 가지다 DOM의 요소 값을 변경했습니다. console.log() 변경 직후의 가치를보고 가지다 변경되었습니다 (DVK의 설명이 올바른 이유를 보여줍니다) - 브라우저가 스택이 고갈되기를 기다리고 있습니다 ( on 핸들러는 반환 할 수 있습니다)와 마감하는 메시지는 결국 돌연변이 작업에 대한 반응으로 런타임에 추가 된 메시지를 실행하고 UI의 돌연변이를 반영하기 위해 결국 메시지를 실행할 수 있습니다.

코드가 실제로 실행을 끝내기를 기다리고 있기 때문입니다. 우리는 "누군가가 이것을 가져 와서 결과와 함께이 기능을 호출합니다. 감사합니다. 이제 우리는 일반적으로 이벤트 기반의 비동기 JavaScript와 마찬가지로 우리가 보통 이벤트 기반의 JavaScript와 마찬가지로 지금 무엇이든 할 수 있습니다." 클릭 이벤트 처리기 기능을 입력하고 DOM 요소를 업데이트하고 다른 기능을 호출하고 다른 기능은 오랫동안 작동 한 다음 반환 한 다음 동일한 DOM 요소를 업데이트하고 업데이트합니다. 그 다음에 우리는 초기 함수에서 돌아와 스택을 효과적으로 비 웁니다. 그리고 그 다음에 브라우저는 대기열의 다음 메시지를받을 수 있으며, 이는 내부 "ON-DOM-MUTAL"유형 이벤트를 트리거하여 미국이 생성 한 메시지 일 수 있습니다.

브라우저 UI는 현재 실행중인 프레임이 완료 될 때까지 UI를 업데이트 할 수 없거나 선택하지 않을 수 있습니다 (함수가 반환 됨). 개인적으로, 나는 이것이 제한보다 디자인에 의한 것이라고 생각합니다.

setTimeout 그럼 일이 작동합니까? 그것은 자체 프레임에서 장기 실행 기능에 대한 호출을 효과적으로 제거하여 나중에 실행되도록 예약하기 때문에 그렇게합니다. window 문맥, 그 자체가 할 수 있습니다 즉시 반환하십시오 메시지 대기열이 다른 메시지를 처리하도록 허용합니다. 그리고 아이디어는 DOM에서 텍스트를 변경할 때 JavaScript에서 우리가 트리거 된 UI "업데이트"메시지가 이제 장기 실행 기능에 대한 메시지보다 앞서있어 UI 업데이트가 차단하기 전에 발생합니다. 오랫동안.

a) 장기 실행 기능 여전히 차단됩니다 그것이 실행될 때의 모든 것, 그리고 b) UI 업데이트가 실제로 메시지 대기열에서 UI 업데이트보다 앞서 있음을 보장하지는 않습니다. 2018 년 6 월 크롬 브라우저에서 0 바이올린이 보여주는 문제를 "고정"하지 않습니다. 나는 실제로 UI 업데이트 메시지를 대기해야한다는 것이 논리적으로 보이기 때문에 나는 이것에 의해 약간 줄어드는 것처럼 보이기 때문이다. 왜냐하면 장기 실행 기능을 "나중에"실행하기 전에 트리거가 실행되기 때문이다. 그러나 V8 엔진에 방해가 될 수있는 최적화가있을 수도 있고, 아마도 내 이해가 부족할 수도 있습니다.

좋아, 그래서 사용의 문제는 무엇입니까? setTimeout, 이 특정 사례에 대한 더 나은 솔루션은 무엇입니까?

우선, 사용 문제 setTimeout 이와 같은 모든 이벤트 핸들러에서 다른 문제를 완화하려고 시도하면 다른 코드를 엉망으로 만들기 쉽습니다. 내 작업의 실제 사례는 다음과 같습니다.

이벤트 루프에 대한 잘못된 정보를 얻은 동료는 템플릿 렌더링 코드 사용을 통해 "스레드"JavaScript를 시도했습니다. setTimeout 0 렌더링을 위해. 그는 더 이상 여기에 묻지 않지만 렌더링 속도를 측정하기 위해 타이머를 삽입했다고 가정 할 수 있으며 (기능의 즉각적인 반응이 될 것임)이 접근법을 사용하면 해당 기능의 빠른 응답이 가능하다는 것을 발견했습니다.

첫 번째 문제는 분명합니다. 당신은 JavaScript를 실 수 없으므로 난독 화를 추가하는 동안 여기서 아무것도 얻지 못합니다. 둘째, 이제 가능한 이벤트 청취자의 스택에서 템플릿의 렌더링을 효과적으로 분리하여 바로 템플릿이 렌더링되었을 것으로 예상되는 반면, 그렇지 않았을 수도 있습니다. 그 기능의 실제 동작은 이제 무의식적으로도 실행하거나 의존하는 모든 기능과 마찬가지로 결정적이지 않았습니다. 교육받은 추측을 할 수 있지만 그 행동에 대해 올바르게 코딩 할 수는 없습니다.

논리에 의존하는 새로운 이벤트 핸들러를 작성할 때 "수정"은 또한 사용 setTimeout 0. 그러나 그것은 해결책이 아니며 이해하기 어렵고 코드로 인한 오류를 디버그하는 것은 재미가 없습니다. 때로는 문제가없고, 다른 경우에는 끊임없이 실패한 다음 다시, 때로는 플랫폼의 현재 성능과 당시에 진행되는 다른 일에 따라 산발적으로 작동하고 깨지는 경우가 있습니다. 이것이 제가 개인적 으로이 해킹 사용에 대해 조언하는 이유입니다 (It ~이다 당신이 무엇을하고 있는지, 결과가 무엇인지 알지 않는 한 해킹, 그리고 우리는 모두 그것을 알아야합니다.

근데 뭐 ~할 수 있다 대신 우리는? 참조 된 MDN 기사에서 알 수 있듯이 작업을 여러 메시지로 나누면 (가능하다면) 대기하는 다른 메시지가 작업과 상호 작용하고 실행되는 동안 실행되거나 실행할 수있는 웹 워커를 사용할 수 있습니다. 귀하의 페이지와 함께 계산으로 완료되면 결과를 반환합니다.

아, 그리고 당신이 생각하고 있다면, "음, 나는 장기 실행 기능에 콜백을 넣어 비동기식으로 만들 수 없었습니까?" 콜백은 비동기식으로 만들지 않으며 콜백을 명시 적으로 호출하기 전에 장기 실행 코드를 실행해야합니다.

또 다른 일은 함수 호출을 스택 하단으로 밀어 내고 기능을 재귀 적으로 호출하는 경우 스택 오버플로를 방지하는 것입니다. 이것은 a의 효과가 있습니다 while 루프이지만 JavaScript 엔진에 다른 비동기 타이머를 발사 할 수 있습니다.

Settimeout에 전화하면 페이지가 사용자가 수행하는 모든 것에 반응 할 시간을 제공합니다. 이는 페이지로드 중에 실행되는 기능에 특히 도움이됩니다.

Settimeout이 유용한 다른 경우 :

브라우저가 '동결'되거나 "페이지의 스크립트가 바쁘다"고 말하지 않도록 장기 루프 또는 계산을 더 작은 구성 요소로 나누고 싶습니다.

클릭하면 양식 제출 버튼을 비활성화하려고하지만 Onclick 핸들러의 버튼을 비활성화하면 양식이 제출되지 않습니다. 시간이 0 인 Settimeout은 트릭을 수행하여 이벤트가 종료되고 양식을 제출하기 시작하면 버튼을 비활성화 할 수 있습니다.

다른 코드가 완료되기 전에 실행 루프 및 DOM 렌더링에 대한 답변이 정확합니다. JavaScript의 제로 두 번째 타임 아웃은 코드가 유사하지 않더라도 의사 소도를 읽는 데 도움이됩니다.

크로스 브라우저 / 크로스 플랫폼의 가장 좋은 값은 JavaScript에서 제로 초 타임 아웃에서 실제로 0 (0) 대신 약 20 밀리 초의 약 20 밀리 초입니다. AMD 칩에.

또한 DOM 조작을 포함하지 않는 장기 실행 프로세스는 JavaScript의 진정한 멀티 스레드 실행을 제공하므로 웹 작업자에게 지금 보내야합니다.

Settimout 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();
}

문제는 기존 비 요소에서 JavaScript 작업을 수행하려고하는 것이 었습니다. 요소는 아직로드되지 않았습니다 setTimeout() 요소가 다음과 같은 방법으로로드 할 수있는 시간을 더 많이 제공합니다.

  1. setTimeout() 이벤트가 발생합니다 ansynchronous 따라서 모든 동기 코드 후에 실행되므로 요소가 더 많은로드 할 시간을줍니다. 콜백과 같은 비동기 콜백 setTimeout() 에 배치됩니다 이벤트 대기열 그리고 스택을 켜십시오 이벤트 루프 동기 코드 스택이 비어있는 후.
  2. 기능의 두 번째 인수로서 MS의 값 0 setTimeout() 종종 약간 더 높습니다 (브라우저에 따라 4-10ms). 이 약간 더 높은 시간은 실행에 필요했습니다 setTimeout() 콜백은 이벤트 루프의 '진드기'(진드기가 스택에서 콜백을 밀고있는 곳)의 양으로 인해 발생합니다. 성능과 배터리 수명 이유 때문에 이벤트 루프의 진드기 양은 일정량으로 제한됩니다. 더 적은 초당 1000 회 이상.

JavaScript는 단일 스레드 응용 프로그램이므로 동시에 기능을 실행하지 않으므로이 이벤트 루프를 달성하기 위해 사용됩니다. 따라서 정확히 Settimeout (FN, 0)이 호출 스택이 비어있을 때 실행되는 작업 퀘스트에 고집을 냈습니다. 이 설명이 지루하다는 것을 알고 있으므로이 비디오를 살펴 보는 것이 좋습니다. 이것은 브라우저에서 후드 아래에서 일이 어떻게 작동하는지에 도움이 될 것입니다. 이 비디오를 확인하십시오 :- https://www.youtube.com/watch?time_continue=392&v=8AGHZQKOFBQ

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top