亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

理解javascript異步編程

2019-11-20 10:40:38
字體:
來源:轉載
供稿:網友

一、異步機制

JavaScript的執行環境是單線程的,單線程的好處是執行環境簡單,不用去考慮諸如資源同步,死鎖等多線程阻塞式編程等所需要面對的惱人的問題。但帶來的壞處是當一個任務執行時間較長時,后面的任務會等待很長時間。在瀏覽器端就會出現瀏覽器假死,鼠標無法響應等情況。所以在瀏覽器端,耗時很長的操作都應該異步執行,避免瀏覽器失去響應。所謂異步執行,不同于同步執行(程序的執行順序與任務的排列順序是一致的、同步的),每一個任務有一個或多個回調函數(callback),前一個任務結束后,不是執行后一個任務,而是執行回調函數,后一個任務則是不等前一個任務結束就執行,所以程序的執行順序與任務的排列順序是不一致的、異步的。既然Javascript是單線程的,那它又如何能夠異步的執行呢?

二、Javascript線程模型和事件驅動

JavaScript有一個基于事件循環的并發模式。這個模式與C語言和java有很大不同。

運行時的概念


函數調用形成堆棧幀。

function f(b){  var a = 12;  return a+b+35;}function g(x){  var m = 4;  return f(m*x);}g(21);

當調用函數g時,創建第一個包含g參數和局部變量的幀。當g函數調用f函數時,創建包含f參數和局部變量第二個堆棧幀并推到第一個堆棧幀的頂部。當f返回時,頂部的堆棧幀元素被彈出(只留下g調用)。當g函數返回時,堆棧為空。


堆是一個大型的非結構化區域,對象被分配到堆中。
隊列
一個javascript運行環境包含一個信息隊列,這個隊列是一系列將被執行的信息列表。每一個消息被關聯到一個函數上。當堆棧為空時,從消息隊列中取出一個消息并進行處理。該處理包含調用相關的函數(以及因此產生一個初始化的堆棧幀)。當堆棧再次為空時,消息處理結束。
事件循環

事件循環的名字源于它的實現,經常像下面這樣:

while(queue.waitForMessage()){ queue.processNextMessage();}

queue.waitForMessage同步等待一個消息。

1、運行到完成
每個消息完全處理之后,其它消息才會被處理。這樣的好處就是當一個函數不能被提前,只能等其他函數執行完畢(并且可以修改數據的函數操作)。這不同于C,例如,如果一個函數在一個線程運行時,它可以停在任何點運行在另一個線程一些其他的代碼。這種模式的缺點是,如果一個消息時間過長完成,Web應用程序無法處理像點擊或滾動的用戶交互。該瀏覽器可緩解此與“腳本花費的時間太長運行”對話框。一個很好的做法,遵循的是使信息處理短,如果可能削減一個消息到幾條消息。
2、添加消息
在網頁瀏覽器中,事件可以在任何時候添加,一個事件發生并伴隨事件監聽綁定到事件上。如果沒有事件監聽,則事件丟失。就像點擊一個元素,元素上綁定點擊事件。調用setTimeout時,當函數的第二個參數時間被傳遞進去,將添加一個消息到隊列中。如果在隊列中沒有其他消息,該消息被立即處理;然而,如果有消息,則setTimeout的信息將必須等待其它消息以進行處理。由于這個原因,第二個參數是最小的時間,而不是一個保證時間。
3、幾個運行環境之間的通信
一個web worker或跨域iframe都有自己的堆棧,堆,和消息隊列。兩個不同的運行環境只能通過postMessage的方法發送消息進行通信。這種方法增加了一個消息到其他運行時,如果后者監聽消息事件。
從不阻塞

事件循環模型是javascript的一個很有意思的屬性,不像其它語言,它從不阻塞。假定瀏覽器中有一個專門用于事件調度的實例(該實例可以是一個線程,我們可以稱之為事件分發線程event dispatch thread),該實例的工作就是一個不結束的循環,從事件隊列中取出事件,處理所有很事件關聯的回調函數(event handler)。注意回調函數是在Javascript的主線程中運行的,而非事件分發線程中,以保證事件處理不會發生阻塞。通過事件和回調的I/O操作是一個典型的表現,所以當應用等待索引型數據庫查詢返回或XHR請求返回時,它仍然可以處理其他事情比如用戶輸入。

三、回調

回調是javascript的基礎,函數被作為參數進行傳遞。像下面:

f1();f2();f3();

如果f1中執行了大量的耗時操作,而且f2需要在f1之后執行。則程序可以改為回調的形式。如下:

function f1(callback){  setTimeout(function () {    // f1的大量耗時任務代碼并的到三個結果i,l,you.    console.log("this is function1");    var i = "i", l = "love", y = "you";    if (callback && typeof(callback) === "function") {      callback(i,l,y);    }  }, 50);}function f2(a, b, c) {  alert(a + " " + b + " " + c);  console.log("this is function2");}function f3(){console.log("this is function3");}f1(f2);f3();

運行結果:

this is function3this is function1i love youthis is function2

采用這種方式,我們把同步操作變成了異步操作,f1不會堵塞程序運行,相當于先執行程序的主要邏輯,將耗時的操作推遲執行。
回調函數的優點是簡單,輕量級(不需要額外的庫)。缺點是各個部分之間高度耦合(Coupling),流程會很混亂,而且每個任務只能指定一個回調函數。某個操作需要經過多個非阻塞的IO操作,每一個結果都是通過回調,產生意大利面條式(spaghetti)的代碼。

operation1(function(err, result) {  operation2(function(err, result) {    operation3(function(err, result) {      operation4(function(err, result) {        operation5(function(err, result) {          // do something useful        })      })    })  })})

四、事件監聽

另一種思路是采用事件驅動模式。任務的執行不取決于代碼的順序,而取決于某個事件是否發生。

// plain, non-jQuery version of hooking up an event handlervar clickity = document.getElementById("clickity");clickity.addEventListener("click", function (e) {  //console log, since it's like ALL real world scenarios, amirite?  console.log("Alas, someone is pressing my buttons…");});// the obligatory jQuery version$("#clickity").on("click", function (e) {  console.log("Alas, someone is pressing my buttons…");});

也可以自定義事件進行監聽,關于自定義事件,屬于另外一部分的內容。這種方法的優點是比較容易理解,可以綁定多個事件,每個事件可以指定多個回調函數,而且可以"去耦合"(Decoupling),有利于實現模塊化。缺點是整個程序都要變成事件驅動型,運行流程會變得很不清晰。

五、觀察者模式

我們假定,存在一個"信號中心",某個任務執行完成,就向信號中心"發布"(publish)一個信號,其他任務可以向信號中心"訂閱"(subscribe)這個信號,從而知道什么時候自己可以開始執行。這就叫做"發布/訂閱模式"(publish-subscribe pattern),又稱"觀察者模式"(observer pattern)。

var pubsub = (function(){  var q = {}    topics = {},    subUid = -1;  //發布消息  q.publish = function(topic, args) {    if(!topics[topic]) {return;}    var subs = topics[topic],      len = subs.length;    while(len--) {      subs[len].func(topic, args);    }    return this;  };  //訂閱事件  q.subscribe = function(topic, func) {    topics[topic] = topics[topic] ? topics[topic] : [];    var token = (++subUid).toString();    topics[topic].push({      token : token,      func : func    });    return token;  };  return q;  //取消訂閱就不寫了,遍歷topics,然后通過保存前面返回token,刪除指定元素})();//觸發的事件var f2 = function(topics, data) {  console.log("logging:" + topics + ":" + data);  console.log("this is function2");}function f1(){   setTimeout(function () {      // f1的任務代碼      console.log("this is function1");    //發布消息'done'    pubsub .publish('done', 'hello world');    }, 1000);}pubsub.subscribe('done', f2);f1();

上面代碼的運行結果為:

this is function1logging:done:hello worldthis is function2

觀察者模式的實現方法有很多種,也可以直接借用第三方庫。這種方法的性質與"事件監聽"類似(觀察者模式和自定義事件非常相似),但是明顯優于后者。觀察者模式和事件監聽一樣具有良好的去耦性,并且有一個消息中心,通過對消息中心的處理,可以良好地監控程序運行。

六、Promises對象

Promises的概念是由CommonJS小組的成員在 Promises/A規范 中提出來的。Promises被逐漸用作一種管理異步操作回調的方法,但出于它們的設計,它們遠比那個有用得多。Promise允許我們以同步的方式寫代碼,同時給予我們代碼的異步執行。

function f1(){  var def = $.Deferred();  setTimeout(function () {    // f1的任務代碼    console.log("this is f1");    def.resolve();   }, 500);  return def.promise();}function f2(){  console.log("this is f2");}f1().then(f2);

上面代碼的運行結果為:

this is f1this is f2

上面引用的是jquery對Promises/A的實現,jquery中還有一系列方法,具體可參考:Deferred Object.關于Promises,強烈建議讀一下You're Missing the Point of Promises.還有很多第三方庫實現了Promises,如:Q、Bluebird、 mmDeferred 等。Promise(中文:承諾)其實為一個有限狀態機,共有三種狀態:pending(執行中)、fulfilled(執行成功)和rejected(執行失敗)。其中pending為初始狀態,fulfilled和rejected為結束狀態(結束狀態表示promise的生命周期已結束)。狀態轉換關系為:pending->fulfilled,pending->rejected。隨著狀態的轉換將觸發各種事件(如執行成功事件、執行失敗事件等)。 下節具體講述狀態機實現js異步編程。

七、狀態機

Promises的本質實際就是通過狀態機來實現的,把異步操作與對象的狀態改變掛鉤,當異步操作結束的時候,發生相應的狀態改變,由此再觸發其他操作。這要比回調函數、事件監聽、發布/訂閱等解決方案,在邏輯上更合理,更易于降低代碼的復雜度。關于Promises可參考:JS魔法堂:剖析源碼理解Promises/A規范 。

八、ES6對異步的支持

這是一個新的技術,成為2015年的ECMAScript(ES6)標準的一部分。該技術的規范已經完成,但實施情況在不同的瀏覽器不同,在瀏覽器中的支持情況如下。

var f1 = new Promise(function(resolve, reject) {  setTimeout(function () {    // f1的任務代碼    console.log("this is f1");    resolve("Success");  }, 500); });function f2(val){  console.log(val + ":" + "this is f2");}function f3(){  console.log("this is f3")}f1.then(f2);f3();

以上代碼在Chrome 版本43中的運行結果為:

this is f3this is f1Success:this is f2

以上就是針對javascript異步編程的了解學習,之后還有相關文章進行分享,不要錯過哦。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩精品欧美激情| 日韩在线免费视频| 国产精品综合网站| 奇米4444一区二区三区| 日韩精品在线视频美女| 欧美猛交ⅹxxx乱大交视频| 国产在线拍偷自揄拍精品| 亚洲аv电影天堂网| 亚洲精品福利视频| 亚洲精品久久久久中文字幕二区| 欧美精品生活片| 日韩av在线看| 亚洲一区二区三区视频播放| 欧美成人手机在线| 亚洲jizzjizz日本少妇| 日韩成人激情影院| 欧美理论电影在线播放| 欧美裸体xxxx极品少妇软件| 成人xxxx视频| 日韩大陆欧美高清视频区| 亚洲无av在线中文字幕| 亚洲欧洲日产国码av系列天堂| 国产精品成人播放| 欧美久久精品一级黑人c片| 国产这里只有精品| 亚洲色图色老头| 伊人久久久久久久久久久久久| 97久久久久久| 国产日本欧美一区二区三区在线| 欧美午夜精品在线| 国产精品成人aaaaa网站| 日本一区二区在线免费播放| 欧美日韩国产中文字幕| 久久精品色欧美aⅴ一区二区| 国产精品男人的天堂| 91久久国产婷婷一区二区| 欧美日韩免费观看中文| 久久久久久久一区二区| 午夜精品三级视频福利| 日韩大胆人体377p| 91影院在线免费观看视频| xxx一区二区| 亚洲一区亚洲二区亚洲三区| 亚洲国产美女久久久久| 91九色国产在线| 欧美成人免费全部观看天天性色| 精品国产乱码久久久久久婷婷| 欧美美最猛性xxxxxx| 在线观看国产欧美| 91av在线不卡| 91高清在线免费观看| 国产精品久久久久影院日本| 亚洲激情免费观看| 精品偷拍一区二区三区在线看| 日韩成人av一区| 亚洲aⅴ男人的天堂在线观看| 日韩中文娱乐网| 久久精品视频在线| 三级精品视频久久久久| 亚洲国产一区二区三区在线观看| 91精品国产91久久久久福利| 中文字幕在线视频日韩| 亚洲女人被黑人巨大进入| 久久中文字幕在线视频| 日韩经典第一页| 日本伊人精品一区二区三区介绍| 大胆欧美人体视频| 久久伊人色综合| 国产91成人video| 成人h片在线播放免费网站| 色哟哟亚洲精品一区二区| 亚洲最大福利网站| 亚洲午夜性刺激影院| 91国语精品自产拍在线观看性色| 欧美性猛交xxxxx水多| 色噜噜久久综合伊人一本| 97国产精品人人爽人人做| 亚洲跨种族黑人xxx| 久久亚洲欧美日韩精品专区| 岛国视频午夜一区免费在线观看| 久久精品中文字幕电影| 一二美女精品欧洲| 久久精品99国产精品酒店日本| 亚洲最大中文字幕| 成人性教育视频在线观看| 国产视频久久网| 亚洲欧美日韩一区二区在线| 68精品国产免费久久久久久婷婷| 国产精品久久久久久久一区探花| 国产精品成人观看视频国产奇米| 国产这里只有精品| 久久免费精品视频| 视频一区视频二区国产精品| 亚洲福利视频在线| 97精品在线视频| 成人激情在线播放| 久久国产精品首页| 日韩av免费看网站| 国产日韩中文字幕| 亚洲欧美日韩一区二区在线| 国产精品三级久久久久久电影| 黑人巨大精品欧美一区二区三区| 日韩欧美高清在线视频| 中文字幕精品视频| 欧美日韩免费网站| 亚洲欧美日韩爽爽影院| 欧美高清不卡在线| 久久久免费电影| 亚洲第一男人天堂| 亚洲天堂av综合网| 中文字幕亚洲二区| 欧美丝袜第一区| 欧美日韩亚洲激情| 成人两性免费视频| 91地址最新发布| 91系列在线播放| 日韩风俗一区 二区| 欧美超级免费视 在线| 亚洲精品一区中文字幕乱码| 久久精品91久久香蕉加勒比| 国产亚洲综合久久| 青青草原成人在线视频| 久久久久久18| 亚洲人成五月天| 欧日韩不卡在线视频| 国产精品入口尤物| 亚洲免费影视第一页| 国产精品无av码在线观看| 日韩中文字幕国产精品| 日本精品中文字幕| 一区二区三区四区视频| 欧美激情综合色| 91九色蝌蚪国产| 中文字幕在线成人| 91久久精品国产91久久性色| 中文字幕成人在线| 精品中文字幕久久久久久| 国产香蕉一区二区三区在线视频| 国产精品三级网站| 日韩69视频在线观看| 日韩精品高清在线| 国产91|九色| 国内成人精品视频| 日韩精品有码在线观看| 国产精品日韩专区| 亚洲图片在区色| 国产亚洲a∨片在线观看| 欧美成人国产va精品日本一级| 热99久久精品| 欧美黄色成人网| 日韩精品高清视频| 中文字幕亚洲综合久久筱田步美| 久久久国产视频91| 色哟哟亚洲精品一区二区| 97在线视频精品| 俺也去精品视频在线观看| 国产日韩欧美另类| 国产精品第1页| 成人黄色中文字幕| 国产精品一区二区三区久久久| 国产欧美va欧美va香蕉在| 亚洲欧美成人一区二区在线电影| 欧美精品18videosex性欧美| 久久久这里只有精品视频|