亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

詳解JavaScript Alert函數(shù)執(zhí)行順序問題

 更新時間:2021年05月27日 10:30:11   作者:枕邊書  
本文主要介紹了Javascript的Alert函數(shù)執(zhí)行順序問題,對此感興趣的同學,可以實驗一下,以便解決平時遇到的一些奇怪的問題。

問題

前幾天使用 JavaScript 寫 HTML 頁面時遇到了一個奇怪的問題:

我想實現(xiàn)的功能是通過 confirm() 彈窗讓用戶選擇不同的需求,每次選擇后都將選擇結(jié)果暫時輸出到頁面上,最后一次選擇結(jié)束后再一次性將選項傳到后端處理。 代碼類似于:

var step1 = confirm("exec step1?");
$('#result').html($('#result').html() + "\n" + step1);
var step2 = confirm("exec step2?");
$('#result').html($('#result').html() + "\n" + step2);
var step3 = confirm("exec step3?");
$('#result').html($('#result').html() + "\n" + step3);

send(step1, step2, step3);

可是代碼運行后卻發(fā)現(xiàn):每次在執(zhí)行完 confirm 函數(shù),用戶選擇選項之后,頁面并沒有刷新,step1, step2 的結(jié)果沒有實時刷新到頁面上,而是到最后一步跟 step3 一塊顯示了出來。

后續(xù)嘗試了 alert() 和 prompt() 這兩個跟 confirm 類似的彈對話框函數(shù),情況都與此相同,它們都會跳過頁面渲染先被執(zhí)行。

此時,還有更詭異的情況,我們給某一個 div 里賦值后,立刻 alert 此 div 里的內(nèi)容,會發(fā)現(xiàn) alert 顯示正確的內(nèi)容,而 div 里的內(nèi)容卻沒有更新,并且會一直阻塞到我們點擊確定。

如圖:

alert、prompt、confirm 三個函數(shù)都類似,接下來我們就用最簡單的 alert 來說。

分析

解決這個問題之前先了解一下它是怎么導致的,而要了解它需要從 JavaScript 的線程模型說起。

JavaScript 引擎是單線程運行的,瀏覽器無論在什么時候都只且只有一個線程在運行 JavaScript 程序,初衷是為了減少 DOM 等共享資源的沖突??墒菃尉€程永遠會面臨著一個問題,那就是某一段代碼阻塞會導致后續(xù)所有的任務(wù)都延遲。又由于 JavaScript 經(jīng)常需要操作頁面 DOM 和發(fā)送 HTTP 請求,這些 I/O 操作耗時一般都比較長,一旦阻塞,就會給用戶非常差的使用體驗。

于是便有了事件循環(huán)(event loop)的產(chǎn)生,JavaScript 將一些異步操作或 有I/O 阻塞的操作全都放到一個事件隊列,先順序執(zhí)行同步 CPU代碼,等到 JavaScript 引擎沒有同步代碼,CPU 空閑下來再讀取事件隊列的異步事件來依次執(zhí)行。

這些事件包括:

  • setTimeout() 設(shè)置的異步延遲事件;
  • DOM 操作相關(guān)如布局和繪制事件;
  • 網(wǎng)絡(luò) I/O 如 AJAX 請求事件;
  • 用戶操作事件,如鼠標點擊、鍵盤敲擊。

解決

明白了原理, 再解決這個問題就有了方向,我們來分析這個問題:

1.由于頁面渲染是 DOM 操作,會被 JavaScript 引擎放入事件隊列;

2.alert() 是 window 的內(nèi)置函數(shù),被認為是同步 CPU代碼;

3.JavaScript 引擎會優(yōu)先執(zhí)行同步代碼,alert 彈窗先出現(xiàn);

4.alert 有特殊的阻塞性質(zhì),JavaScript 引擎的執(zhí)行被阻塞??;

5.點擊 alert 的“確定”,JavaScript 沒有了阻塞,執(zhí)行完同步代碼后,又讀取事件隊列里的 DOM 操作,頁面渲染完成。

由上述原因,導致了詭異的 “Alert執(zhí)行順序問題”。 我們無法將頁面渲染變成同步操作,那么只好把 alert() 變?yōu)楫惒酱a,從而才能在頁面渲染之后執(zhí)行。

對于這個解決方向,我們有兩種方法可以使用:

替換 Alert() 函數(shù)

首先我們考慮替換掉 alert 函數(shù)的功能。其實大多數(shù)情況下我們替換掉 alert 并不是它不符合我們期待的執(zhí)行順序,而是因為它實在是太丑了,而且也不支持各種美化,可以想像在一個某一特定主題的網(wǎng)站上忽然彈出來一個灰色單調(diào)的對話框是多么不和諧。

這個我們可以考慮 Bootstrap 的 modal 模塊,Bootstrap 在絕大多數(shù)網(wǎng)站上都在應(yīng)用,而多引入一個 modal 模塊也不會有多大影響。我們使用 modal 構(gòu)造一個彈出對話框的樣子,使用 modal 的 modal('toggle')/modal('show')/modal('hide') 方法可以很方便地控制 modal 的顯隱。

替換掉對話框后,我們還需要解決后續(xù)代碼執(zhí)行的問題。使用 alert 函數(shù)時,我們點擊確定后代碼還會繼續(xù)執(zhí)行,而使用我們自定義的對話框可沒有這種功能了,需要考慮把后續(xù)代碼綁定在對話框的點擊按鈕上,這就需要使用 DOM 的 onclick 屬性了,我們將后續(xù)函數(shù)內(nèi)容抽出一個新的函數(shù),在彈出對話框后將這個函數(shù)綁定在按鈕的 onclick 事件上即可。

這里還需要注意,新函數(shù)內(nèi)應(yīng)該包括關(guān)閉 modal 對話框的內(nèi)容。

當然,我們還可以再優(yōu)化一下,抽象出來一個用來彈出對話框的函數(shù)替代 alert 函數(shù),示例如下:

window.alert = function (message, callbackFunc) {
    $('#alertContent').html(message);
    $('#modal').show();
    $('#confirmButton').onclick(function () {
        $('#modal').hide();
        callbackFunc();
    });
};

如此,我們在需要彈出框時調(diào)用新的 alert 函數(shù),并傳入 callbackFunc ,在里面做后續(xù)的事情就可以了。

setTimeOut函數(shù)

當然,并不是所有人都愿意使用新的對話框替換 alert 函數(shù)的對話框,總感覺上面的方法不是特別的優(yōu)雅,對此,我們可以采用另外的方法解決這個問題。

前端的同學應(yīng)該對 setTimeout() 這個函數(shù)不陌生,使用它,可以延遲執(zhí)行某些代碼。而對于延遲執(zhí)行的代碼,JavaScript 引擎總是把這些代碼放到事件隊列里去,再去檢查是否已經(jīng)到了執(zhí)行時間,再適時執(zhí)行。代碼進入事件隊列,就意味著代碼變成和頁面渲染事件一樣異步了。由于事件隊列是有序的,我們?nèi)绻?setTimeout 延時執(zhí)行,就可以實現(xiàn)在頁面渲染之后執(zhí)行 alert 的功能了。

setTimeout 的函數(shù)原型為 setTimeout(code, msec),code 是要變?yōu)楫惒降拇a或函數(shù),msec 是要延時的時間,單位為毫秒。這里我們不需要它延時,只需要它變?yōu)楫惒骄托辛?,所以可以?msec 設(shè)置為 0;

同樣,alert 之后的代碼我們也需要處理,將它們跟 alert 一塊放到 setTimeout 里異步執(zhí)行。這樣,代碼就變?yōu)?setTimeout("alert('msg');doSomething();", 0);,如果覺得代碼不夠美觀或字符串不好處理的話,可以將后續(xù)代碼封裝成一個函數(shù)放到 doSomething() 里即可。

小結(jié)

在上面的兩個解決方案中,都利用了 JavaScript 的回調(diào)函數(shù),前者將函數(shù)所為 alert 的參數(shù)并綁定到 DOM 的 onclick 事件,后者使用 setTimeout 將函數(shù)轉(zhuǎn)為異步執(zhí)行。JavaScript 的回調(diào)函數(shù)確實非常強大,使用起來也很簡單,但是卻有一個隱含的問題,就是回調(diào)嵌套問題,單層的回調(diào)很容易理解,但如果要實現(xiàn)像我的需求一樣,有多個 alert 和頁面渲染輪流執(zhí)行的情況,需要面臨的可能就是“回調(diào)地獄”, onclick 事件綁定里的函數(shù)又要嵌套綁定 onclick 函數(shù), setTimeout 里還需要另一個 setTimeout 語句,一旦出現(xiàn)問題,排查起來就比較麻煩了。

以上就是詳解JavaScript Alert函數(shù)執(zhí)行順序問題的詳細內(nèi)容,更多關(guān)于JavaScript Alert函數(shù)執(zhí)行順序問題的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論