国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JavaScript單線程、加載與模塊化

shevy / 2530人閱讀

摘要:單線程與瀏覽器多線程是單線程的因為運行在瀏覽器中,是單線程的,每個一個線程。若以多線程的方式操作這些,則可能出現操作的沖突。零延遲零延遲并不是意味著回調函數立刻執行。異步編程的中方法包括回調函數事件監聽采用事件驅動模式。

JavaScript單線程與瀏覽器多線程

Javascript是單線程的:因為JS運行在瀏覽器中,是單線程的,每個window一個JS線程。作為瀏覽器腳本語言,JavaScript的主要用途是與用戶互動,以及操作DOM。若以多線程的方式操作這些DOM,則可能出現操作的沖突。假設有兩個線程同時操作一個DOM元素,線程1要求瀏覽器刪除DOM,而線程2卻要求修改DOM樣式,這時瀏覽器就無法決定采用哪個線程的操作。

瀏覽器不是單線程的,引擎可能存在如下線程:

javascript引擎線程

界面渲染線程

瀏覽器事件觸發線程

Http請求線程等

Event Loop

事件循環機制:
主線程從"任務隊列"中讀取事件,這個過程是循環不斷的,所以整個的這種運行機制又稱為Event Loop(事件循環)。主線程運行的時候,產生堆(heap)和棧(stack),棧中的代碼調用各種外部API,它們在"任務隊列"中加入各種事件(click,load,done)。只要棧中的代碼執行完畢,主線程就會去讀取"任務隊列",依次執行那些事件所對應的回調函數。

執行棧:所有同步任務都在主線程上執行,形成一個執行棧;

任務隊列:主線程之外,還存在一個"任務隊列"(task queue)。只要異步任務有了運行結果,就在"任務隊列"之中放置一個事件,當棧為空時,就會從任務隊列中取出一個任務并執行。

定時器:
定時器包括setTimeout與setInterval兩個方法。它們的第二個參數是指定其回調函數推遲每隔多少毫秒數后執行。
零延遲 setTimeout(func, 0):零延遲并不是意味著回調函數立刻執行。它取決于主線程當前是否空閑與“任務隊列”里其前面正在等待的任務。當計時器時間規定的時候,回調函數會被添加到“任務隊列”中,等到執行棧的任務執行完畢,就會來執行這里的任務。所以,有的時候即使計時器已經到0了,也會不立即執行計時器中的回調任務。

Ajax異步請求:
在發起ajax請求的時候,瀏覽器會開一個線程去執行這一步驟,發請求這一步是屬于執行棧中的同步任務,在請求發完之后就會執行棧中的下一個任務,而等到請求有了結果,就會把結果放入“任務隊列”中,等待執行;

JavaScript異步編程

JavaScript是單線程的,所謂“單線程”,就是同一時間只能執行一個任務。如果有多個任務,就必須排隊,直到前一個任務完成。這種模式的好處就是實現比較簡單,尤其在瀏覽器環境中,可以避免很多不必要的麻煩。壞處就是如果一個任務耗時很長,那么該任務后面的任務就必須一直等待,導致整個頁面都卡住無法繼續往下執行。

為了解決這個問題,JavaScript將任務的執行模式分為兩類,一個是同步模式,另一個是異步模式。

"同步模式"就是上一段的模式,后一個任務等待前一個任務結束,然后再執行,程序的執行順序與任務的排列順序是一致的、同步的;"異步模式"則完全不同,每一個任務有一個或多個回調函數(callback),前一個任務結束后,不是執行后一個任務,而是執行回調函數,后一個任務則是不等前一個任務結束就執行,所以程序的執行順序與任務的排列順序是不一致的、異步的。

JS異步編程的4中方法包括:

回調函數:

f1();
f2();

function f1(callback){
    setTimeout(function(){
        callback();
    })
}

f1(f2);

事件監聽:采用事件驅動模式。任務的執行不取決于代碼的順序,而取決于某個事件是否發生。

//jQuery
f1.on("done", f2);

function f1(){
   setTimeout(function () {
       //do something
     f1.trigger("done");//執行完成后,立即觸發done事件,從而開始執行f2。
   }, 1000);
}

發布/訂閱:又稱觀察者模式

jQuery.subscribe("done", f2);//訂閱"done"這個信號

function f1(){
   setTimeout(function () {
     //do something
     jQuery.publish("done");//f1()執行完之后,發出"done"這個信號,f2開始執行
   }, 1000);
}

jQuery.unsubscribe("done", f2);//取消訂閱

Promises:ES6原生提供了Promise對象。所謂Promise對象,就是代表了未來某個將要發生的事件(通常是一個異步操作)。它的好處在于,有了Promise對象,就可以將異步操作以同步操作的流程表達出來,避免了層層嵌套的回調函數。此外,Promise對象還提供了一整套完整的接口,使得可以更加容易地控制異步操作。

var promise = new Promise(function(resolve, reject) {
  if (/* 異步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});

promise.then(function(value) {
  // success
}, function(value) {
  // failure
});

ES6模塊管理

ECMAScript 6基于export和import,定義了模塊的導出和導入規范,在語言標準層面實現了模塊機制。該標準的目標是創建一種能夠兼容CommoneJS和AMD兩標準的規范,即可以像CommoneJS一樣語法簡潔、使用單一的接口且支持循環依賴,又可以像AMD支持異步加載和可配置的模塊加載。

大致來說,當 JS 引擎運行一個模塊的時候,它的行為大致可歸納為以下四步:

解析:引擎實現會閱讀模塊的源碼,并且檢查是否有語法錯誤。

加載:引擎實現會(遞歸地)加載所有被引入的模塊。

鏈接:引擎實現會為每個新加載的模塊創建一個作用域,并且將模塊中的聲明綁定填入其中,包括從其他模塊中引入的。

JS加載

動態加載常用的4種方法:

document.write:document.write("");

動態改變已有script的src屬性:js.src = "package.js";

動態創建script元素:

var script = document.createElement("script");
script.src = "XXX";
script.type = "XXX";
document.head.appendChild(script);

用XMLHTTP取得要腳本的內容,再創建 Script 對象。

項目中加載JS的方法:
在頁面底部寫一個自調用函數,加載入口JS,然后入口中的方法執行,加載需要的其他JS。

在VM平臺上,可以選擇將幾個模塊分組打包到一個入口文件中,然后在這個入口文件中,將每個組動態生成一個script標簽,插入head中。

異步加載:
瀏覽器在渲染一個頁面的時候,遇到一個

閱讀需要支付1元查看
<