[javascript] innerHTML은 비동기식입니까?

나는 나 자신을 바보로 만들지 않기를 바라지 만,이 두 줄의 코드에서 무슨 일이 일어나고 있는지 이해하려고 노력하고 있습니다.

document.body.innerHTML = 'something';
alert('something else');

내가 관찰하는 것은 HTML이 업데이트되기 전에 경고가 표시된다는 것입니다 (또는 HTML이 업데이트되었지만 페이지가 새로 고쳐 지거나 다시 그려지지 않았거나 무엇이든)

내가 의미하는 바를 보려면 이 코드 펜 을 확인하십시오.

심지어 퍼팅 참고 사항 alert으로는 setTimeout(..., 0)도움이되지 않습니다. innerHTML실제로 페이지를 업데이트 하는 데 더 많은 이벤트 루프가 필요한 것 같습니다 .

편집하다:

Chrome을 사용하고 있다는 것을 잊고 다른 브라우저를 확인하지 않았습니다. Chrome에서만 볼 수있는 것 같습니다. 그럼에도 불구하고 왜 그런 일이 일어나는지 여전히 관심이 있습니다.



답변

innerHTML 설정은 DOM을 변경할 수있는 대부분의 변경과 마찬가지로 동기식입니다. 그러나 웹 페이지 렌더링 은 다른 이야기입니다.

(DOM은 “Document Object Model”의 약자입니다. 데이터를 표현한 “모델”일뿐입니다. 사용자가 화면에서 보는 것은 모델이 어떻게 보이는지에 대한 그림입니다. 따라서 모델을 즉시 변경하는 것은 아닙니다. 사진 변경-업데이트하는 데 약간의 시간이 걸립니다.)

JavaScript를 실행하고 웹 페이지를 렌더링하는 것은 실제로 개별적으로 발생합니다. (이벤트 루프에서 – 체크 아웃 페이지 실행에 먼저 모든 자바 스크립트, 단순하게 말하면 이 우수한 비디오 자세한 내용에 대한)를 다음 브라우저는 사용자가 볼 수 있도록 웹 페이지에 대한 변경 사항을 렌더링하는. 이것이 “차단”이 그토록 큰 문제인 이유입니다. 계산 집약적 인 코드를 실행하면 브라우저가 “JS 실행”단계를지나 “페이지 렌더링”단계로 들어가 페이지가 멈추거나 끊기는 것을 방지 할 수 있습니다.

Chrome의 파이프 라인은 다음과 같습니다.

여기에 이미지 설명 입력

보시다시피 모든 JavaScript가 먼저 발생합니다. 그런 다음 페이지의 스타일이 지정되고, 레이아웃이 지정되고, 페인트되고, 합성됩니다 ( “렌더링”). 이 파이프 라인이 모든 프레임에서 실행되는 것은 아닙니다. 변경된 페이지 요소 (있는 경우) 및 다시 렌더링해야하는 방법에 따라 다릅니다.

참고 : alert()또한 동기식이며 JavaScript 단계 중에 실행되기 때문에 웹 페이지 변경 사항을 확인하기 전에 경고 대화 상자가 나타납니다.

이제 “잠시만 요, 파이프 라인의 ‘JavaScript’단계에서 정확히 무엇이 실행됩니까? 모든 코드가 초당 60 번 실행됩니까?”라고 질문 할 수 있습니다. 대답은 “아니오”이며 JS 이벤트 루프가 작동하는 방식으로 돌아갑니다. JS 코드는 이벤트 리스너, 시간 초과 등과 같은 항목에서 스택에있는 경우에만 실행됩니다. 이전 비디오를 참조하십시오 (정말).

https://developers.google.com/web/fundamentals/performance/rendering/


답변

예, 작동하기 때문에 동기식입니다 (계속해서 콘솔에 입력하십시오).

document.body.innerHTML = 'text';
alert(document.body.innerHTML);// you will see a 'text' alert

페이지가 변경되기 전에 경고가 표시되는 이유는 브라우저 렌더링에 더 많은 시간이 걸리고 자바 스크립트가 한 줄씩 실행하는 것만 큼 빠르지 않기 때문입니다.


답변

innerHTML실제 숙박 시설은 동 기적으로 업데이트됩니다 않지만, 이러한 변화가 발생하게 시각적 다시 그리기가 비동기 적으로 발생합니다.

DOM의 시각적 렌더링은 Chrome에서 비동기식이며 현재 JavaScript 함수 스택이 지워지고 브라우저가 새 이벤트를 자유롭게 수락 할 때까지 발생하지 않습니다. 다른 브라우저는 별도의 스레드를 사용하여 JavaScript 코드 및 브라우저 렌더링을 처리하거나 경고가 다른 이벤트의 실행을 중지하는 동안 일부 이벤트가 우선 순위를 갖도록 할 수 있습니다.

이를 두 가지 방법으로 볼 수 있습니다.

  1. for(var i=0; i<1000000; i++) { }경고 전에 추가하는 경우 브라우저에 다시 그리기를 수행 할 충분한 시간을 주었지만 함수 스택이 지워지지 않았기 때문에 ( add아직 실행 중) 그렇지 않습니다 .

  2. alert비동기를 통해 지연 setTimeout(function() { alert('random'); }, 1)하면 다시 그리기 프로세스가 setTimeout에 의해 지연된 함수보다 앞서게됩니다.

    • 시간 제한을 사용하는 경우에는 작동하지 않습니다. 0Chrome이 0다른 이벤트보다 먼저 (또는 적어도 다시 그리기 이벤트보다 앞서) 시간 제한에 이벤트 큐 우선 순위를 부여하기 때문일 수 있습니다 .

답변