詳談javascript異步編程
異步編程帶來的問題在客戶端Javascript中并不明顯,但隨著服務(wù)器端Javascript越來越廣的被使用,大量的異步IO操作使得該問題變得明顯。許多不同的方法都可以解決這個(gè)問題,本文討論了一些方法,但并不深入。大家需要根據(jù)自己的情況選擇一個(gè)適于自己的方法。
本文為大家詳細(xì)介紹js中的異步編程,具體內(nèi)容如下
一 關(guān)于事件的異步
事件是JavaScript中最重要的一個(gè)特征,nodejs就是利用js這一異步而設(shè)計(jì)出來的。所以這里講一下事件機(jī)制。
在一個(gè)js文件中,如果要運(yùn)行某一個(gè)函數(shù),有2中手段,一個(gè)就是直接調(diào)用,比如foo(),第二就是利用事件來觸發(fā),這中函數(shù)也叫回調(diào)函數(shù),比如傳遞給setTimeout函數(shù)和onready屬性。
1.setTimeout函數(shù)中的事件異步
setTimeout本質(zhì)上也是一種異步事件,當(dāng)延遲時(shí)間到的時(shí)候觸發(fā)該事件,但是有的有的時(shí)候(其實(shí)也是大部分時(shí)候)都不會(huì)按照給定的延遲時(shí)間執(zhí)行,先看下面的代碼
var start = new Date(); setTimeout(function() { console.log('settimeout1:',new Date()-start); }, 500); while (new Date() - start < 1000) { console.log('in while'); } document.getElementById('test').addEventListener('click', function(){ console.log('test:',new Date()-start); }, false) for(var i=0;i<10000;i++){ console.log('in for'); } setTimeout(function(){ console.log('settimeout2: ',new Date()-start); },1000); /* 10214 in while index.jsp (第 19 行) 10000 in for index.jsp (第 25 行) settimeout1: 2263 index.jsp (第 16 行) settimeout2: 3239 index.jsp (第 28 行) test: 10006 index.jsp (第 22 行) test: 28175 index.jsp (第 22 行) test: 28791 index.jsp (第 22 行) test: 28966 index.jsp (第 22 行) */
如果按照正常的理解,延遲函數(shù)應(yīng)該在500毫秒之后打斷while循環(huán),而事實(shí)上并沒有,并且,我在while循環(huán)和for循環(huán)期間點(diǎn)擊div時(shí)候并沒有立即輸出test,給出的解釋就是:
a)事件隊(duì)列。調(diào)用setTimeout函數(shù)的時(shí)候,會(huì)把傳入它的回調(diào)函數(shù)加入到事件隊(duì)列中去(事件已經(jīng)初始化并且在內(nèi)存了),然后繼續(xù)執(zhí)行后面的代碼,直到再也沒有代碼可以運(yùn)行(沒有正常的運(yùn)行流了,不包括事件函數(shù)等異步的內(nèi)容),就會(huì)從事件隊(duì)列里面pop出一個(gè)合適的事件來運(yùn)行。
b)js是單線程的,事件處理器在線程空閑之前是不會(huì)運(yùn)行的。
2 普通事件的異步和setTimeout類似
二 promise對(duì)象和deferred對(duì)象
1. promise
promise是一種解決ajax等異步編程回調(diào)函數(shù)嵌套太多導(dǎo)致代碼晦澀難懂的解決方案,特別是在nodejs中,異步無處不在。不同的框架對(duì)promise的實(shí)現(xiàn),一下是jquery中的promise的API。
這里不講promise的實(shí)現(xiàn)原理,關(guān)于原理在另外的篇幅中介紹。
傳統(tǒng)的ajax異步編程是這么寫的(jquery1.5之前):
$.get('url', function(){ $.get('url1', function(){ $.get('url2', function(){ }, 'json'); }, 'json'); }, 'json');
這么寫代碼給開發(fā)和維護(hù)帶來了極大的困難,好在jquery1.5以后引入了promise,就可以這么寫了:
$.ajax( "example.php" ) .done(function() { alert("success"); }) .fail(function() { alert("error"); }) .always(function() { alert("complete"); });
現(xiàn)在看上去就明顯簡(jiǎn)單多了。
2.deferred對(duì)象
var nanowrimoing = $.Deferred(); var wordGoal = 5000; nanowrimoing.progress(function(wordCount) { var percentComplete = Math.floor(wordCount / wordGoal * 100); $('#indicator').text(percentComplete + '% complete'); }); nanowrimoing.done(function(){ $('#indicator').text('Good job!'); });
三.worker對(duì)象和多線程
四.異步腳本加載
1.傳統(tǒng)腳本在頁面中的位置
腳本分為兩大類:阻塞式和非阻塞式。這里的阻塞是指加載阻塞而不是運(yùn)行阻塞。
<!DOCTYPE html> <html> <head> <script src="headScript"></script> <script defer src="deferredScript"></script> </head> <body> <script async defer src="chatWidget"></script> <script async defer src="asyncScript"></script> </body> </html>
上面這部分代碼是比較標(biāo)準(zhǔn)的關(guān)于腳本在一個(gè)頁面中的位置,1.其中傳統(tǒng)的未加任何修飾的headScript是阻塞式的腳本,由于瀏覽器從上到下解釋執(zhí)行JavaScript,所以這部分腳本文件在一開始就會(huì)被執(zhí)行,并且在執(zhí)行完之前是DOM是不會(huì)渲染的,但是head標(biāo)簽里面的css會(huì)加載。2.有defer屬性的腳本會(huì)在DOM渲染的同時(shí)進(jìn)行加載,但是會(huì)在DOM渲染完畢之后才開始執(zhí)行,不幸的是,不是所有的瀏覽器都支持defer屬性,所以才會(huì)有了jquery(function)這個(gè)東西。3.同時(shí)帶有async屬性和defer屬性時(shí)候,defer會(huì)覆蓋async,但是單獨(dú)有async的時(shí)候,腳本會(huì)在DOM渲染的時(shí)候加載并且運(yùn)行。
2.可編程的腳本加載
如果不是一開始就在頁面種引入js文件,而是通過用戶交互來實(shí)現(xiàn)動(dòng)態(tài)的加載js腳本,可以通過編程方式加入。
瀏覽器獲取服務(wù)器腳本有2個(gè)方法,ajax獲取并且通過eval函數(shù)執(zhí)行,另外一個(gè)就是在DOM中插入<script>標(biāo)簽,一般用第二種方法,因?yàn)闉g覽器幫助我們生成HTTP請(qǐng)求以及eval會(huì)泄露作用域。
var head = document.getElementsByTagName('head')[0]; var script = document.createElement('script'); script.src = '/js/feature.js'; head.appendChild(script); script.onload = function() { // 現(xiàn)在可以調(diào)用腳本里定義的函數(shù)了 }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家學(xué)習(xí)js異步編程有所幫助。
- JavaScript異步編程之Promise的初步使用詳解
- 深入理解JS異步編程-Promise
- 詳解JavaScript異步編程中jQuery的promise對(duì)象的作用
- javascript使用Promise對(duì)象實(shí)現(xiàn)異步編程
- javascript異步編程代碼書寫規(guī)范Promise學(xué)習(xí)筆記
- Javascript中的異步編程規(guī)范Promises/A詳細(xì)介紹
- Javascript異步編程模型Promise模式詳細(xì)介紹
- JavaScript異步編程Promise模式的6個(gè)特性
- Javascript異步編程之你真的懂Promise嗎
相關(guān)文章
淺談JavaScript變量的自動(dòng)轉(zhuǎn)換和語句
下面小編就為大家?guī)硪黄獪\談JavaScript變量的自動(dòng)轉(zhuǎn)換和語句。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-06-06JS+HTML5實(shí)現(xiàn)上傳圖片預(yù)覽效果完整實(shí)例【測(cè)試可用】
這篇文章主要介紹了JS+HTML5實(shí)現(xiàn)上傳圖片預(yù)覽效果,結(jié)合完整實(shí)例形式分析了javascript上傳圖片本地預(yù)覽的具體操作步驟與相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-04-04Javascript快速實(shí)現(xiàn)瀏覽器系統(tǒng)通知
這篇文章給大家介紹了Javascript快速實(shí)現(xiàn)瀏覽器系統(tǒng)通知的方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2017-08-08JS模擬百度搜索框和選項(xiàng)卡的實(shí)現(xiàn)
本文主要介紹了JS模擬百度搜索框和選項(xiàng)卡的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-03-03JavaScript中的this指向綁定規(guī)則及常見面試總結(jié)
這篇文章主要為大家介紹了JavaScript中的this指向綁定規(guī)則及箭頭韓碩中的this指向,還b包含了常見面試總結(jié),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12