摘要:異步那些事一基礎(chǔ)知識(shí)異步那些事二分布式事件異步那些事三異步那些事四異步那些事五異步腳本加載事件概念異步回調(diào)首先了講講中兩個(gè)方法和定義和用法方法用于在指定的毫秒數(shù)后調(diào)用函數(shù)或計(jì)算表達(dá)式。功能在事件循環(huán)的下一次循環(huán)中調(diào)用回調(diào)函數(shù)。
JS異步那些事 一 (基礎(chǔ)知識(shí))
JS異步那些事 二 (分布式事件)
JS異步那些事 三 (Promise)
JS異步那些事 四(HTML 5 Web Workers)
JS異步那些事 五 (異步腳本加載)
首先了講講js中 兩個(gè)方法 setTimeout()和 setInterval()
定義和用法:setTimeout() 方法用于在指定的毫秒數(shù)后調(diào)用函數(shù)或計(jì)算表達(dá)式。語法:
setTimeout(callback,time)
callback 必需。要調(diào)用的函數(shù)后要執(zhí)行的 JavaScript 代碼串。
time 必需。在執(zhí)行代碼前需等待的毫秒數(shù)。
setInterval() 方法和setTimeout很相似,可按照指定的周期(以毫秒計(jì))來調(diào)用函數(shù)或計(jì)算表達(dá)式。
比如上述代碼就是可以每隔1000毫秒延遲執(zhí)行timecount函數(shù),不同的是后者是周期的執(zhí)行timecount函數(shù),
SetInterval為自動(dòng)重復(fù),setTimeout不會(huì)重復(fù)。
JavaScript引擎是單線程運(yùn)行的,瀏覽器無論在什么時(shí)候都只且只有一個(gè)線程在運(yùn)行JavaScript程序.
執(zhí)行上述代碼,可以發(fā)現(xiàn),總的運(yùn)行時(shí)間幾乎要6秒多,因?yàn)槭菃尉€程,會(huì)在while循環(huán)里面消耗5秒的時(shí)間,然后才去執(zhí)行settimeout函數(shù)。
隊(duì)列瀏覽器是基于一個(gè)事件循環(huán)的模型,在這里面,可以有多個(gè)任務(wù)隊(duì)列,比如render是一個(gè)隊(duì)列,響應(yīng)用戶輸入是一個(gè),script執(zhí)行是一個(gè)。任務(wù)隊(duì)列里放的是任務(wù),同一個(gè)任務(wù)來源的任務(wù)肯定在同一個(gè)任務(wù)隊(duì)列里。任務(wù)有優(yōu)先級(jí),鼠標(biāo)或鍵盤響應(yīng)事件優(yōu)先級(jí)高,大概是其他任務(wù)的3倍。
而我們常用的setTimeout函數(shù),其本質(zhì)上也就是向這個(gè)任務(wù)隊(duì)列添加回調(diào)函數(shù),JavaScript引擎一直等待著任務(wù)隊(duì)列中任務(wù)的到來.由于單線程關(guān)系,這些任務(wù)得進(jìn)行排隊(duì),一個(gè)接著一個(gè)被引擎處理.
如果隊(duì)列非空,引擎就從隊(duì)列頭取出一個(gè)任務(wù),直到該任務(wù)處理完,即返回后引擎接著運(yùn)行下一個(gè)任務(wù),在任務(wù)沒返回前隊(duì)列中的其它任務(wù)是沒法被執(zhí)行的.
異步函數(shù)類型 異步IO:首先來看看很典型的一個(gè)例子 ajax
異步計(jì)時(shí):setTimeout,setInterval都是基于事件驅(qū)動(dòng)型的,通常瀏覽器不會(huì)給這個(gè)太快的速度,一般是200次/秒,效率太低了是吧如果遇到有密集型的運(yùn)算的話,那就呵呵了。但是在node.js中還有process.nextTick()這個(gè)強(qiáng)大的東西,運(yùn)行的速度將近10萬次/秒,很可觀。
process.nextTick(callback)
功能:在事件循環(huán)的下一次循環(huán)中調(diào)用 callback 回調(diào)函數(shù)。效果是將一個(gè)函數(shù)推遲到代碼書寫的下一個(gè)同步方法執(zhí)行完畢時(shí)或異步方法的事件回調(diào)函數(shù)開始執(zhí)行時(shí);與setTimeout(fn, 0) 函數(shù)的功能類似,但它的效率高多了。
基于node.js的事件循環(huán)分析,每一次循環(huán)就是一次tick,每一次tick時(shí),v8引擎從事件隊(duì)列中取出所有事件依次進(jìn)行處理,如果遇到nextTick事件,則將其加入到事件隊(duì)尾,等待下一次tick到來時(shí)執(zhí)行;造成的結(jié)果是,nextTick事件被延遲執(zhí)行;
nextTick的確是把某任務(wù)放在隊(duì)列的最后(array.push)
nodejs在執(zhí)行任務(wù)時(shí),會(huì)一次性把隊(duì)列中所有任務(wù)都拿出來,依次執(zhí)行
如果全部順利完成,則刪除剛才取出的所有任務(wù),等待下一次執(zhí)行
如果中途出錯(cuò),則刪除已經(jīng)完成的任務(wù)和出錯(cuò)的任務(wù),等待下次執(zhí)行
如果第一個(gè)就出錯(cuò),則throw error
下面看一下應(yīng)用場景(包含計(jì)算密集型操作,將其進(jìn)行遞歸處理,而不阻塞進(jìn)程):
var http = require("http"); var wait = function (mils) { var now = new Date; while (new Date - now <= mils); }; function compute() { // performs complicated calculations continuously console.log("start computing"); wait(1000); console.log("working for 1s, nexttick"); process.nextTick(compute); } http.createServer(function (req, res) { console.log("new request"); res.writeHead(200, {"Content-Type": "text/plain"}); res.end("Hello World"); }).listen(5000, "127.0.0.1"); compute();異步錯(cuò)誤處理 異步異常的特點(diǎn)
由于js的回調(diào)異步特性,無法通過try catch來捕捉所有的異常:
try { process.nextTick(function () { foo.bar(); }); } catch (err) { //can not catch it }
而對于web服務(wù)而言,其實(shí)是非常希望這樣的:
//express風(fēng)格的路由 app.get("/index", function (req, res) { try { //業(yè)務(wù)邏輯 } catch (err) { logger.error(err); res.statusCode = 500; return res.json({success: false, message: "服務(wù)器異常"}); } });
如果try catch能夠捕獲所有的異常,這樣我們可以在代碼出現(xiàn)一些非預(yù)期的錯(cuò)誤時(shí),能夠記錄下錯(cuò)誤的同時(shí),友好的給調(diào)用者返回一個(gè)500錯(cuò)誤。可惜,try catch無法捕獲異步中的異常。
難道我們就這樣放棄了么? 其實(shí)還有一個(gè)辦法
我們一般通過函數(shù)名傳遞的方式(引用的方式)將要執(zhí)行的操作函數(shù)傳遞給onerror事件,如
window.onerror=reportError; window.onerror=function(){alert("error")}
但我們可能不知道該事件觸發(fā)時(shí)還帶有三個(gè)默認(rèn)的參數(shù),他們分別是錯(cuò)誤信息,錯(cuò)誤頁面的url和錯(cuò)誤行號(hào)。
嵌套式回調(diào)的解嵌套
JavaScript中最常見的反模式做法是,回調(diào)內(nèi)部再嵌套回調(diào)。
這里定義了一個(gè)異步函數(shù)checkPassword,它觸發(fā)了另一個(gè)異步函數(shù)db.query,而后者又可能觸發(fā)另外一個(gè)異步函數(shù)hash。它能用,而且簡潔明了。但是,如果試圖向其添加新特性,它就會(huì)變得毛里毛躁、險(xiǎn)象環(huán)生,比如去處理那個(gè)數(shù)據(jù)庫錯(cuò)誤,而不是拋出錯(cuò)誤、記錄嘗試訪問數(shù)據(jù)庫的次數(shù)、阻塞訪問數(shù)據(jù)庫,等等。
下面我們換一種寫法,雖然這種寫法很啰嗦但是可讀性更高而且更易擴(kuò)展。
在平時(shí)寫嵌套時(shí),我們應(yīng)該盡量避免多層嵌套,不然中間某個(gè)地方出錯(cuò)了將會(huì)導(dǎo)致你投入更多的時(shí)間去debug。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/87756.html
摘要:向添加一個(gè)事件監(jiān)聽器當(dāng)傳遞消息時(shí),會(huì)執(zhí)行事件監(jiān)聽器中的代碼。終止當(dāng)我們創(chuàng)建對象后,它會(huì)繼續(xù)監(jiān)聽消息即使在外部腳本完成之后直到其被終止為止。 JS異步那些事 一 (基礎(chǔ)知識(shí))JS異步那些事 二 (分布式事件)JS異步那些事 三 (Promise)JS異步那些事 四(HTML 5 Web Workers)JS異步那些事 五 (異步腳本加載) 什么是 Web Worker? 當(dāng)在 HTML ...
摘要:異常處理異常處理一直是回調(diào)的難題,而提供了非常方便的方法在一次調(diào)用中,任何的環(huán)節(jié)發(fā)生,都可以在最終的中捕獲到錯(cuò)誤處理基本的小結(jié)具體的很多的用法可以參考阮一峰的入門教程,還有就是上面提到的電子書。 JS異步那些事 一 (基礎(chǔ)知識(shí))JS異步那些事 二 (分布式事件)JS異步那些事 三 (Promise)JS異步那些事 四(HTML 5 Web Workers)JS異步那些事 五 (異步腳本...
摘要:遵循的是異步模塊定義規(guī)范,遵循的是通用模塊定義規(guī)范。不同的腳本加載這個(gè)模塊,得到的都是同一個(gè)實(shí)例。關(guān)于異步那些事就寫到這里了,很多地方理解的不夠深刻希望大家多多指教。 JS異步那些事 一 (基礎(chǔ)知識(shí))JS異步那些事 二 (分布式事件)JS異步那些事 三 (Promise)JS異步那些事 四(HTML 5 Web Workers)JS異步那些事 五 (異步腳本加載) 異步腳本加載 阻塞性...
摘要:聲明的變量不得改變值,這意味著,一旦聲明變量,就必須立即初始化,不能留到以后賦值。 雖然今年沒有換工作的打算 但為了跟上時(shí)代的腳步 還是忍不住整理了一份最新前端知識(shí)點(diǎn) 知識(shí)點(diǎn)匯總 1.HTML HTML5新特性,語義化瀏覽器的標(biāo)準(zhǔn)模式和怪異模式xhtml和html的區(qū)別使用data-的好處meta標(biāo)簽canvasHTML廢棄的標(biāo)簽IE6 bug,和一些定位寫法css js放置位置和原因...
閱讀 1180·2021-11-22 13:54
閱讀 2428·2021-09-22 15:36
閱讀 2735·2019-08-30 15:54
閱讀 802·2019-08-30 15:53
閱讀 3168·2019-08-30 15:53
閱讀 515·2019-08-29 15:21
閱讀 2862·2019-08-28 18:28
閱讀 3004·2019-08-26 13:37