成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Javascript異步編程詳解

開發 前端
Javascript語言將任務的執行模式分成兩種:同步(Synchronous)和異步(Asynchronous)."異步模式"非常重要。在瀏覽器端,耗時很長的操作都應該異步執行,避免瀏覽器失去響應,最好的例子就是Ajax操作。在服務器端,"異步模式"甚至是唯一的模式,因為執行環境是單線程的,如果允許同步執行所有http請求,服務器性能會急劇下降,很快就會失去響應。

前言

你可能知道,Javascript語言的執行環境是"單線程"(single thread)。

所謂"單線程",就是指一次只能完成一件任務。如果有多個任務,就必須排隊,前面一個任務完成,再執行后面一個任務,以此類推。

這種模式的好處是實現起來比較簡單,執行環境相對單純;壞處是只要有一個任務耗時很長,后面的任務都必須排隊等著,會拖延整個程序的執行。常見的瀏覽器無響應(假死),往往就是因為某一段Javascript代碼長時間運行(比如死循環),導致整個頁面卡在這個地方,其他任務無法執行。

為了解決這個問題,Javascript語言將任務的執行模式分成兩種:同步(Synchronous)和異步(Asynchronous).

"異步模式"非常重要。在瀏覽器端,耗時很長的操作都應該異步執行,避免瀏覽器失去響應,***的例子就是Ajax操作。在服務器端,"異步模式"甚至是唯一的模式,因為執行環境是單線程的,如果允許同步執行所有http請求,服務器性能會急劇下降,很快就會失去響應。

setTimeout 函數的弊端

延時處理當然少不了 setTimeout這個神器,很多人對 setTimeout函數的理解就是:延時為 n 的話,函數會在 n 毫秒之后執行。事實上并非如此,這里存在三個問題:

一個是 setTimeout函數的及時性問題, setTimeout是存在一定時間間隔的,并不是設定 n 毫秒執行,他就是 n 毫秒執行,可能會有一點時間的延遲,setInterval 和 setTimeout 函數運轉的最短周期是 5ms 左右,這個數值在 HTML規范 中也是有提到的:

  • Let timeout be the second method argument, or zero if the argument was omitted.如果 timeout 參數沒有寫,默認為 0
  • If nesting level is greater than 5, and timeout is less than 4, then increase timeout to 如果嵌套的層次大于 5 ,并且 timeout 設置的數值小于 4 則直接取 4.

其次是while循環會阻塞setTimeout的執行

看這段代碼:

  1. var t = true
  2.  
  3. window.setTimeout(function (){ 
  4.     t = false
  5. },1000); 
  6.  
  7. while (t){} 
  8.  
  9. alert('end');  

結果是死循環導致setTimeout不執行,也導致alert不執行

js是單線程,所以會先執行while(t){}再alert,但這個循環體是死循環,所以永遠不會執行alert。

至于說為什么不執行setTimeout,是因為js的工作機制是:當線程中沒有執行任何同步代碼的前提下才會執行異步代碼,setTimeout是異步代碼,所以setTimeout只能等js空閑才會執行,但死循環是永遠不會空閑的,所以setTimeout也永遠不會執行。

第三是,try..catch捕捉不到他的錯誤

異步編程方法

回調函數

這是異步編程最基本的方法。

假定有兩個函數f1和f2,后者等待前者的執行結果。

  1. function f1(callback){ 
  2.   setTimeout(function () { 
  3.     // f1的任務代碼 
  4.     callback(); 
  5.   }, 1000); 
  6. f1(f2);  

采用這種方式,我們把同步操作變成了異步操作,f1不會堵塞程序運行,相當于先執行程序的主要邏輯,將耗時的操作推遲執行。

回調函數的優點是簡單、容易理解和部署,缺點是不利于代碼的閱讀和維護,各個部分之間高度耦合(Coupling),流程會很混亂,而且每個任務只能指定一個回調函數。

事件監聽

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

  1. f1.on('done', f2); 
  2. function f1(){ 
  3.   setTimeout(function () { 
  4.     // f1的任務代碼 
  5.     f1.trigger('done'); 
  6.   }, 1000); 
  7.  

JS 和 瀏覽器提供的原生方法基本都是基于事件觸發機制的,耦合度很低,不過事件不能得到流程控制

Promises對象

Promises對象是CommonJS工作組提出的一種規范,目的是為異步編程提供統一接口。

Promises可以簡單理解為一個事務,這個事務存在三種狀態:

  • 已經完成了 resolved
  • 因為某種原因被中斷了 rejected
  • 還在等待上一個事務結束 pending

簡單說,它的思想是,每一個異步任務返回一個Promises對象,該對象有一個then方法,允許指定回調函數,這樣寫的優點在于,回調函數變成了鏈式寫法,程序的流程可以看得很清楚

Promises就是一個事務的管理器。他的作用就是將各種內嵌回調的事務用流水形式表達,其目的是為了簡化編程,讓代碼邏輯更加清晰。

Promises可以分為:

  • 無錯誤傳遞的 Promises,也就是事務不會因為任何原因中斷,事務隊列中的事項都會被依次處理,此過程中 Promises只有pending和 resolved兩種狀態,沒有 rejected狀態。
  • 包含錯誤的 Promises,每個事務的處理都必須使用容錯機制來獲取結果,一旦出錯,就會將錯誤信息傳遞給下一個事務,如果錯誤信息會影響下一個事務,則下一個事務也會 rejected,如果不會,下一個事務可以正常執行,依次類推。

此處留坑講generator實現異步編程

封裝好的實現

jquery的Deferred對象

簡單說,Deferred對象就是jquery的回調函數解決方案。在英語中,defer的意思是"延遲",所以Deferred對象的含義就是"延遲"到未來某個點再執行。

首先,回顧一下jquery的ajax操作的傳統寫法:

  1. $.ajax({ 
  2.     url: "test.html"
  3.     success: function(){ 
  4.       alert("哈哈,成功了!"); 
  5.     }, 
  6.     error:function(){ 
  7.       alert("出錯啦!"); 
  8.     } 
  9.   });  

有了Deferred對象以后,寫法是這樣的:

  1. $.ajax("test.html"
  2.  .done(function(){ alert("哈哈,成功了!"); }) 
  3.  .fail(function(){ alert("出錯啦!"); });  

可以看到,done()相當于success方法,fail()相當于error方法。采用鏈式寫法以后,代碼的可讀性大大提高。

了解jQuery.Deferred對象可以看下面這個表格。

 when.js

AngularJS內置的Kris Kowal的Q框架,和cujoJS的when.js,兩者都是Promises/A規范的實現

when.js實例

  1. var getData = function() { 
  2.     var deferred = when.defer(); 
  3.  
  4.     $.getJSON(api, function(data){ 
  5.         deferred.resolve(data[0]); 
  6.     }); 
  7.  
  8.     return deferred.promise; 
  9.  
  10. var getImg = function(src) { 
  11.     var deferred = when.defer(); 
  12.  
  13.     var img = new Image(); 
  14.  
  15.     img.onload = function() { 
  16.         deferred.resolve(img); 
  17.     }; 
  18.  
  19.     img.src = src; 
  20.  
  21.     return deferred.promise; 
  22.  
  23. var showImg = function(img) { 
  24.     $(img).appendTo($('#container')); 
  25.  
  26. getData() 
  27. .then(getImg) 
  28. .then(showImg);  

看***三行代碼,是不是一目了然,非常的語義化

  1. var deferred = when.defer(); 

定義了一個deferred對象。

  1. deferred.resolve(data); 

在異步獲取數據完成時,把數據作為參數,調用deferred對象的resolve方法。

  1. return deferred.promise; 

返回了deferred對象的Promises屬性。

此處留坑講之前用過的step.js

擴展閱讀

Javascript既是單線程又是異步的,請問這二者是否沖突,以及有什么區別?

Answer1:Javascript本身是單線程的,并沒有異步的特性。

由于 Javascript的運用場景是瀏覽器,瀏覽器本身是典型的 GUI 工作線程,GUI 工作線程在絕大多數系統中都實現為事件處理,避免阻塞交互,因此產生了 Javascript異步基因。此后種種都源于此。

Answer2: JS的單線程是指一個瀏覽器進程中只有一個JS的執行線程,同一時刻內只會有一段代碼在執行(你可以使用IE的標簽式瀏覽試試看效果,這時打開的多個頁面使用的都是同一個JS執行線程,如果其中一個頁面在執行一個運算量較大的function時,其他窗口的JS就會停止工作)。

而異步機制是瀏覽器的兩個或以上常駐線程共同完成的,例如異步請求是由兩個常駐線程:JS執行線程和事件觸發線程共同完成的,JS的執行線程發起異步請求(這時瀏覽器會開一條新的HTTP請求線程來執行請求,這時JS的任務已完成,繼續執行線程隊列中剩下的其他任務),然后在未來的某一時刻事件觸發線程監視到之前的發起的HTTP請求已完成,它就會把完成事件插入到JS執行隊列的尾部等待JS處理。又例如定時觸發(setTimeout和setinterval)是由瀏覽器的定時器線程執行的定時計數,然后在定時時間把定時處理函數的執行請求插入到JS執行隊列的尾端(所以用這兩個函數的時候,實際的執行時間是大于或等于指定時間的,不保證能準確定時的)。

所以,所謂的JS的單線程和異步更多的應該是屬于瀏覽器的行為,他們之間沒有沖突,更不是同一種事物,沒有什么區別不區別的。

setTimeout(fn,0)立即執行的問題

首先,不會立即執行,原因:

setTimeout(fn,0)的作用很簡單,就是為了把fn放到運行隊列的***去執行。也就是說,無論setTimeout(fn,0)寫在哪,都可以保證在隊列的***執行。js解析器會把setTimeout(fn,0)里的fn壓到隊列的***,因為它是異步操作。有個延時,具體是16ms還是4ms取決于瀏覽器

立即執行還是有可能的,只要在你調用setTimeout的時候,滿足下面兩個條件:

  1. 剛好執行到了當前這一輪事件循環的底部。
  2. 剛好此時事件隊列為空。

那么setTimeout的回調函數就可以立即執行。當然“立即執行”的意思是在任何其他代碼前執行。

責任編輯:龐桂玉 來源: segmentfault
相關推薦

2020-10-15 13:29:57

javascript

2015-04-22 10:50:18

JavascriptJavascript異

2014-05-23 10:12:20

Javascript異步編程

2017-07-13 12:12:19

前端JavaScript異步編程

2021-06-02 09:01:19

JavaScript 前端異步編程

2011-11-11 15:47:22

JavaScript

2021-06-06 16:56:49

異步編程Completable

2021-12-10 07:47:30

Javascript異步編程

2011-11-10 10:23:56

Jscex

2021-06-06 19:51:07

JavaScript異步編程

2023-12-04 13:22:00

JavaScript異步編程

2011-07-27 14:10:43

javascript

2022-10-31 09:00:24

Promise數組參數

2013-04-01 15:38:54

異步編程異步編程模型

2016-10-21 11:04:07

JavaScript異步編程原理解析

2013-01-07 10:44:00

JavaScriptjQueryJS

2013-03-08 09:33:25

JavaScript同步異步

2012-03-31 11:04:32

ibmdw

2021-11-01 22:36:04

JavaScript

2011-11-16 13:22:38

Jscex
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 精品国产乱码久久久久久丨区2区 | 欧美精品在线观看 | 麻豆久久久久久 | 久久久精品网站 | 日韩欧美国产精品一区 | 亚洲自拍一区在线观看 | 久久激情五月丁香伊人 | 在线观看毛片网站 | 视频一二三区 | 日本激情视频在线播放 | 91精品国产乱码久久久久久 | www.天天操 | 午夜av免费| 久久久久免费观看 | 亚洲男人天堂2024 | 日日摸日日添日日躁av | 国产精品一区在线观看 | 狠狠爱视频 | 日韩精品久久一区二区三区 | 日本三级网址 | 在线免费看91| 黄色一级大片在线免费看产 | 欧产日产国产精品v | 国产精品欧美一区二区 | wwww.8888久久爱站网 | 日韩三极 | 日韩在线视频观看 | 亚欧精品 | 免费在线观看91 | 国产精品久久影院 | 国产精品国产三级国产aⅴ中文 | 国产精品九九视频 | 日本爱爱| 国产成人高清视频 | 久久久久久久久久久91 | 日本高清在线一区 | 久久精品一区 | 国产在线精品一区二区 | 免费一看一级毛片 | 岛国一区 | 国产黄色麻豆视频 |