非同步操作概述

2022-09-13 16:12:14 字數 3011 閱讀 8408

單執行緒模型指的是,j**ascript只在乙個執行緒上執行。也就是說,j**ascript同時只能執行乙個任務,其他的任務都必須在後面排隊等待。

程式裡面的所有任務,可以分為兩類:同步任務和非同步任務。

j**ascript執行時,除了乙個正在執行的主線程,引擎還提供乙個任務佇列,裡面是各種需要當前程式處理的非同步任務。(實際上,根據非同步任務的型別,存在多個任務佇列)

首先主線程會去執行所有的同步任務。等到同步任務全部執行完,就會去看任務佇列裡面的非同步任務。如果滿足條件,那麼非同步任務就重新進入主線程開始執行,這時它就變成同步任務了。等執行完,下乙個非同步任務在進入主線程開始執行。一旦任務佇列清空,程式就結束執行。

非同步任務的寫法通常是**函式。一旦非同步任務重新進入主線程,就會執行物件的**函式。如果乙個非同步任務沒有**函式,就不會進入任務佇列。

j**ascript引擎怎麼知道非同步任務有沒有結果,能不能進入主線程呢?答案是引擎在不停的檢查,一遍又一遍,只要同步任務執行完了,引擎就會去檢查那些掛起來的非同步任務,是不是可以進入主線程了。這種迴圈檢查的機制,就叫做事件迴圈。

**函式是非同步操作最基本的方法。

function f1(callback) 

function f2()

f1(f2);

**函式的優點是簡單、容易理解和實現,缺點是不利於**的閱讀和維護,各個部分之間高度耦合。

另一種思路是採用事件驅動模式。非同步任務的執行不取決於**的順序,而取決於某個事件是否發生。

還是以f1和f2為例。首先,為f1繫結乙個時間(這裡採用的jquery的寫法)。

f1.on("done", f2);
上面**的意思是,當f1發生done事件,就執行f2。然後對f1進行改寫:

function f1() , 1000);

}

上面**中,f1.trigger("done")表示,執行完成後,立即觸發done事件,從而開始執行f2。

這種方法的優點時比較容易理解,可以繫結多個事件,每個事件可以指定多個**函式,而且可以去耦合,有利於實現模組化。

事件完全可以理解成訊號,如果存在乙個訊號中心,某個任務執行完成,就想訊號中心發布乙個訊號,其他任務可以向訊號中心訂閱這個訊號。這就叫做發布訂閱模式,又稱觀察者模式。

這個模式有多種實現,下面採用的是ben alman的tiny pub/sub,這是jquery的乙個外掛程式。

首先f2向訊號中心jquery訂閱done訊號。

jquery.subscribe("done", f2);
然後f1做如下改寫。

function f1() , 1000);

}

上面**中,jquery.publish("done")的意思是,f1執行完成後,向訊號中心jquery發布done訊號,從而引發f2的執行。

f2執行完成後,可以取消訂閱。

jquery.unsubscribe("done", f2);
如果有多個非同步操作,就存在乙個流程控制的問題:如何確定非同步操作執行的順序,以及如何保證遵守這種順序。

function async(arg, callback) , 1000);

}

上面**的async函式是乙個非同步任務,非常耗時,每次執行需要1秒才能完成,然後在呼叫**函式。

如果有六個這樣的非同步任務,需要全部完成後,才能執行最後的final函式。請問應該如何安排操作流程?

function final(value) 

async(1, function (value) );

});});

});});

上面**中,六個**函式的巢狀,不僅寫起來麻煩,容易出錯,而且難以維護。

我們可以編寫乙個流程控制函式,讓它來控制非同步任務,乙個任務完成以後,再執行另乙個。這就叫序列執行。

var items = [1, 2, 3, 4, 5, 6];

var results = ;

function async(arg, callback) , 1000);

}function final(value)

function series(item) );

} else

}series(items.shift());

注意,上面的寫法需要六秒,才能完成整個指令碼。

流程控制函式也可以是並行執行,即所有非同步任務同時執行,等到全部完成以後,才執行final函式。

var items = [1, 2, 3, 4, 5, 6];

var results = ;

function async(arg, callback) , 1000);

}function final(value)

items.foreach(function (item)

});});

上面**中,foreach方法會同時發起六個非同步任務,等到它們全部完成以後才會執行final函式。

相比而言,上面的寫法只要一秒,就能完成指令碼。這就是說,並行執行的效率比較高,但是在於如果並行的任務較多,很容易耗盡系統資源,拖慢執行速度。因此有個第三種流程控制方式。

所謂並行和序列的結合,就是設定乙個門檻,每次最多只能並行執行n個非同步任務,這樣就避免了過分占用資源。

var items = [1, 2, 3, 4, 5, 6];

var results = ;

var running = 0;

var limit = 2;

function async(arg, callback) , 1000);

}function final(value)

function launcher() else if (running === 0)

});running++;

}}launcher();

高效能非同步爬蟲概述

同步呼叫 即提交乙個任務後就在原地等待任務結束,等到拿到任務的結果後再繼續下一行 效率低下,呼叫乙個任務,就在原地等待任務結束拿到結果後才繼續往後執行。好處 在伺服器端使用多執行緒 或多程序 的目的是讓每個連線都擁有獨立的執行緒 或程序 這樣任何乙個連線的阻塞都不會影響其他的連線。缺點 在遇到要同時...

基於事件的非同步模式概述

msdn 那些同時執行多項任務 但仍能響應使用者互動的應用程式通常需要實施一種使用多執行緒的設計方案。system.threading 命名空間提供了建立高效能多執行緒應用程式所必需的所有工具,但要想有效地使用這些工具,需要有豐富的使用多執行緒軟體工程的經驗。對於相對簡單的多執行緒應用程式,back...

8 非同步操作

對於遊戲開發而言,經常使用到非同步相關操作,因此在使用moduleframework之前應該提供乙個非同步操作的類。以後相關的非同步操作均繼承這個類 asyncoperation 先貼出 ifndef async operation h define async operation h includ...