做者:心葉
時間:2019-03-08 09:45html
先列出個人理解,而後再從具體的例子中說明:ajax
DOM從操做到渲染結束,我想先用一個具體的例子來講明。canvas
例子說明:把img標籤先追加到頁面,而後把img裏面的內容繪製到canvas上,代碼以下:瀏覽器
<body> <div id='target'></div> <canvas id='canvas'></canvas> <script> var template = '<img ' + 'id="img" ' + 'width="300" ' + 'height="150" ' + 'src="data:image/svg+xml;charset=utf-8,<svg xmlns=\'http://www.w3.org/2000/svg\'><foreignObject ' + 'width=\'120\' ' + 'height=\'50\' ' + '><body xmlns=\'http://www.w3.org/1999/xhtml\'>' + '<p>這是一個例子</p>' + '</body></foreignObject></svg>" />'; // 第一步,添加到頁面 document.getElementById('target').innerHTML = template; // 第二步:繪製到canvas上 document.getElementById('canvas') .getContext('2d') .drawImage(document.getElementById('img'), 0, 0); </script> </body>
看看運行效果:異步
canvas上什麼也沒有繪製出來,而img上面是有內容的(也就是「這是一個例子」這段文字)。svg
接着,在img添加到頁面後,繪製canvas前添加一個延遲,咱們修改一下第二步地方的代碼以下:spa
window.setTimeout(function () { document.getElementById('canvas') .getContext('2d') .drawImage(document.getElementById('img'), 0, 0); }, 100);
再次運行,查看效果:
線程
內容出來了。3d
所以,異步是存在的,只不過是在DOM操做仍是渲染上就不清楚了。code
接着上面的例子,想證實DOM操做是同步的很簡單,依舊修改第二步的代碼以下:
window.setTimeout(function () { document.getElementById('canvas') .getContext('2d') .drawImage(document.getElementById('img22'), 0, 0); }, 100);
咱們修改drawImage方法查找結點的id爲一個錯誤的'img22',顯然查找不到,運行結果以下:
咱們看見瀏覽器報錯了,所以,若是DOM操做是異步的,在沒有添加延遲的時候不該該是什麼都沒有繪製出來,而是應該報錯,所以DOM是同步的,那麼渲染就是異步的。
例子結束,完整代碼請見評論(方便你們閱讀放到評論去)。
應該不少地方都說過,js是單線程的,嚴格的說,是指JS引擎中負責解釋和執行JavaScript代碼的線程只有一個,除此以外,其實還有事件觸發線程、ajax請求線程等,所以,應該說:同步是單線程可能更準確些。
另外,同步會阻塞異步,看一下下面的代碼:
setTimeout(function() { console.log('異步執行了'); }, 0); while(true);
由於同步代碼while條件一直爲真,你在看見『異步執行了』前估計先看見瀏覽器頁面卡卡的。
DOM操做只是結點操做,而頁面最終的效果還會有render渲染樹等參與,所以,雖然DOM操做是同步的,而你指望的「DOM操做」卻不必定是同步的,包括調用外設(外設要看具體設備,有的設備會阻塞瀏覽器執行,什麼意思,就是瀏覽器的異步操做也會中止,結合這裏的異步操做的理解,就能夠解釋一些奇怪現象了)等,須要在平常開發的時候注意。