摘要:異步本質(zhì)上應(yīng)該就是多線程語言的產(chǎn)物。如果是多線程的異步,假死的應(yīng)該是運(yùn)行方法的線程,而方法仍然會(huì)按預(yù)期打印出。當(dāng)然了,按我個(gè)人的理解,應(yīng)該說是是的回調(diào)函數(shù)。
引子
每個(gè)故事都有由來。前兩天在看 gulp 的時(shí)候,看到了它有個(gè) promise 的玩意兒,然后的然后,這兩天就掉進(jìn)了 javascript 的異步和回調(diào)的坑里面去了。
其間搜索了 javascript promise,看到了一堆好文章。大概給個(gè) List 吧。
https://software.intel.com/zh-cn/articles/asynchronized-javascript-pro...
http://stackoverflow.com/questions/7104474/how-does-asynchronous-javas...
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Glob...
http://www.ruanyifeng.com/blog/2012/12/asynchronous_javascript.html
http://krasimirtsonev.com/blog/article/7-lines-JavaScript-library-for-...
http://segmentfault.com/q/1010000000140970
http://www.alloyteam.com/2014/05/javascript-promise-mode/
看得昏天黑地,大概也理清楚了一點(diǎn),做個(gè)小總結(jié)。
一些概念上面這些文章寫得都挺好,但大部分都是上來直接說怎么異步回調(diào),js的異步有哪些方法。這適合高級選手。我剛開始連啥是異步,啥是回調(diào)都不太清楚,這些方法自然也比較難理解。所以還是打好基礎(chǔ),先弄清楚異步、回調(diào)這些基本概念比較好。
同步與異步先看個(gè)例子。
javascriptfoo(); bar();
程序運(yùn)行一般是同步的(synchronous),即按照書寫的順序執(zhí)行。在上述例子中,bar 方法會(huì)在 foo 方法執(zhí)行完之后,再執(zhí)行。
異步(asynchronous)與同步相對,即在前一個(gè)方法未執(zhí)行完時(shí),就開始運(yùn)行后一個(gè)方法。在上述例子中,先執(zhí)行 foo 方法,foo 方法沒執(zhí)行完,就開始執(zhí)行 bar 方法。
總而言之,同步就是順序執(zhí)行,異步就是不完全按順序執(zhí)行。
異步的好處從異步的概念中可以發(fā)現(xiàn),程序異步運(yùn)行,可以提高程序運(yùn)行的效率,不必等一個(gè)程序跑完,再跑下一個(gè)程序,特別當(dāng)這兩個(gè)程序是無關(guān)的時(shí)候。兩個(gè)程序在一定時(shí)間內(nèi),可以是同時(shí)運(yùn)行的。寫服務(wù)器的時(shí)候應(yīng)該會(huì)碰到很多這樣的例子。可以想象,如果服務(wù)器的程序都是同步的,那并發(fā)什么的就不存在了吧。
阻塞與非阻塞這一點(diǎn)是我自己簡單的理解。
阻塞就是說一個(gè)程序沒運(yùn)行完,它后面的程序是無法運(yùn)行的。
而非阻塞則相反,一個(gè)程序如果因?yàn)楦鞣N原因(網(wǎng)絡(luò)、代碼量等)沒運(yùn)行完的時(shí)候,其他的程序也是可以繼續(xù)運(yùn)行的。
單線程與多線程這一點(diǎn)也是我自己的簡單理解。
單線程是指程序運(yùn)行只有一個(gè)通道,不同的方法需要排隊(duì)執(zhí)行。
而很多語言都可以提供多線程的功能,相當(dāng)于開了幾個(gè)通道運(yùn)行程序,使得程序可以在不同的線程中運(yùn)行,不會(huì)相互影響。
多線程、非阻塞、異步從上述基本概念中可以發(fā)現(xiàn),異步如果發(fā)生在多線程語言中,會(huì)十分自然且符合邏輯。異步本質(zhì)上應(yīng)該就是多線程語言的產(chǎn)物。因?yàn)橹挥性诙嗑€程語言中才能夠?qū)崿F(xiàn)程序之間相互不干擾,不產(chǎn)生阻塞。
JS 中的異步有了上面的一些基本概念,那么下面來說說正題,JS中的異步。
我們都知道 JS 是一個(gè)單線程的語言,永遠(yuǎn)只有一個(gè)通道在運(yùn)行程序。那么既然它是個(gè)單線程又如何會(huì)有異步呢?
JS 中所謂的異步,應(yīng)該被稱為偽異步(pseudo asynchronous)。這是因?yàn)?JS 語言中的異步,會(huì)產(chǎn)生阻塞,并會(huì)相互干擾。
我們來看一下 setTimeout 如何模擬 JS 中的異步。
javascriptvar foo = function(){ console.log("foo begins"); setTimeout(function(){ console.log("foo finishes"); },1000); }; var bar = function(){ console.log("bar executed"); } foo(); bar();
上述過程執(zhí)行的時(shí)候,會(huì)打印出
foo begins
bar executed
foo finishes
所以,在上述代碼塊中,在前一方法(foo)執(zhí)行時(shí),后一方法(bar)也可以執(zhí)行。符合異步的基本概念,程序并不按順序執(zhí)行。
說是模擬是因?yàn)?,你可以?console.log("foo begins"); 理解成會(huì)運(yùn)行 1 秒的一個(gè)代碼行,運(yùn)行完后,會(huì)跳出foo finishes。而中間這 1 秒運(yùn)行的時(shí)候,后面的 bar 方法也是可以運(yùn)行的。這樣就模擬了一個(gè)異步的效果。
我們將上述代碼塊稍做修改
javascriptvar foo = function(){ console.log("foo begins"); setTimeout(function(){ console.log("foo finishes"); },1000); }; var bar = function(){ while(){ } } foo(); bar();
你會(huì)發(fā)現(xiàn) 1 秒之后 foo finishes 并沒有被打印出來。這是因?yàn)?bar 方法是個(gè)死循環(huán),使得 js 引擎假死,導(dǎo)致了 foo 方法也沒有被運(yùn)行完。如果是多線程的異步,假死的應(yīng)該是運(yùn)行 bar 方法的線程,而 foo 方法仍然會(huì)按預(yù)期打印出 foo finishes。當(dāng)然了,其實(shí)這個(gè)死循環(huán)也只是模擬 bar 方法塊程序運(yùn)行的時(shí)間將很長。實(shí)際上,如果 bar 方法運(yùn)行的時(shí)間超過了 1 秒,比方說是 5 秒,那么 foo finishes 也將在 5 秒之后被打印出來。這個(gè)本質(zhì)上取決于 JS 單線程程序塊按隊(duì)列執(zhí)行的特性。
所以 JS 中的異步并不能像普通的異步一樣,實(shí)現(xiàn)非阻塞和不干擾。
雖然 JS 中的異步有其先天的缺陷,但是這種異步的思想,仍然能被 JS 程序開發(fā)人員所借鑒。畢竟,異步是可以大大提高程序運(yùn)行效率的。
也正是由于 JS 本身是單線程程序的關(guān)系,所以 JS 中異步的實(shí)現(xiàn),并不能像其他語言一樣,簡單地多開個(gè)線程就可以解決。
目前我看的集中方法主要有回調(diào)、事件類方法、promise等。
先說說回調(diào)是什么吧。
回調(diào)(callback)這種名詞就跟函數(shù)(function)一樣,乍一看是比較難懂的,至少我是這樣的。
根據(jù)sf上這個(gè)問答的解釋,可以明確,把一個(gè)函數(shù)作為參數(shù)傳入到另一個(gè)函數(shù)中,那么這個(gè)作為參數(shù)的函數(shù)就叫做回調(diào)函數(shù)。如:
javascriptvar foo = function(callback){ // foo method callback(); }; foo(bar);
其中,bar 就是一個(gè)回調(diào)函數(shù)。當(dāng)然了,按我個(gè)人的理解,應(yīng)該說是 bar 是 foo 的回調(diào)函數(shù)。
To be Continued時(shí)間問題,具體的實(shí)現(xiàn)方式和理解還沒好好看,日后再做細(xì)細(xì)梳理。上述理解如有偏頗,歡迎討論指正。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/91510.html
摘要:到這里,我已經(jīng)發(fā)出了一個(gè)請求買漢堡,啟動(dòng)了一次交易。但是做漢堡需要時(shí)間,我不能馬上得到這個(gè)漢堡,收銀員給我一個(gè)收據(jù)來代替漢堡。到這里,收據(jù)就是一個(gè)承諾保證我最后能得到漢堡。 同期異步系列文章推薦談一談javascript異步j(luò)avascript異步中的回調(diào)javascript異步之Promise.all()、Promise.race()、Promise.finally()javascr...
摘要:回調(diào)函數(shù),一般在同步情境下是最后執(zhí)行的,而在異步情境下有可能不執(zhí)行,因?yàn)槭录]有被觸發(fā)或者條件不滿足。同步方式請求異步同步請求當(dāng)請求開始發(fā)送時(shí),瀏覽器事件線程通知主線程,讓線程發(fā)送數(shù)據(jù)請求,主線程收到 一直以來都知道JavaScript是一門單線程語言,在筆試過程中不斷的遇到一些輸出結(jié)果的問題,考量的是對異步編程掌握情況。一般被問到異步的時(shí)候腦子里第一反應(yīng)就是Ajax,setTimse...
摘要:如果你把函數(shù)的指針地址作為參數(shù)傳遞給另一個(gè)函數(shù),當(dāng)這個(gè)指針被用來調(diào)用其所指向的函數(shù)時(shí),我們就說這是回調(diào)函數(shù)?;卣{(diào)函數(shù)不是由該函數(shù)的實(shí)現(xiàn)方直接調(diào)用,而是在特定的事件或條件發(fā)生時(shí)由另外的一方調(diào)用的,用于對該事件或條件進(jìn)行響應(yīng)。 同期異步系列文章推薦談一談javascript異步j(luò)avascript異步與promisejavascript異步之Promise.all()、Promise.ra...
摘要:由于引擎同一時(shí)間只執(zhí)行一段代碼這是由單線程的性質(zhì)決定的,所以每個(gè)代碼塊阻塞了其它異步事件的進(jìn)行。這意味著瀏覽器將等待著一個(gè)新的異步事件發(fā)生。異步的任務(wù)執(zhí)行的順序是不固定的,主要看返回的速度。 我們經(jīng)常說JS是單線程的,比如node.js研討會(huì)上大家都說JS的特色之一是單線程的,這樣使JS更簡單明了,可是大家真的理解所謂JS的單線程機(jī)制嗎?單線程時(shí),基于事件的異步機(jī)制又該當(dāng)如何,這些知識(shí)...
摘要:異步回調(diào)被作為實(shí)參傳入另一函數(shù),并在該外部函數(shù)內(nèi)被調(diào)用,用以來完成某些任務(wù)的函數(shù),稱為回調(diào)函數(shù)。回調(diào)函數(shù)經(jīng)常被用于繼續(xù)執(zhí)行一個(gè)異步完成后的操作,它們被稱為異步回調(diào)?;卣{(diào)函數(shù)是事件循環(huán)回頭調(diào)用到程序中的目標(biāo),隊(duì)列處理到這個(gè)項(xiàng)目的時(shí)候會(huì)運(yùn)行它。 唯一比不知道代碼為什么崩潰更可怕的事情是,不知道為什么一開始它是工作的! 在 ECMA 規(guī)范的最近幾次版本里不斷有新成員加入,尤其在處理異步的問題...
摘要:在異步機(jī)制中,任務(wù)隊(duì)列就是用來維護(hù)異步任務(wù)回調(diào)函數(shù)的隊(duì)列。四對象對象是工作組提出的一種規(guī)范,目的是為異步編程提供統(tǒng)一接口。 異步 1.JavaScript單線程的理解 Javascript語言的執(zhí)行環(huán)境是單線程(single thread)。所謂單線程,就是指一次只能完成一件任務(wù)。如果有多個(gè)任務(wù),就必須排隊(duì),前面一個(gè)任務(wù)完成,再執(zhí)行后面一個(gè)任務(wù),以此類推。 2.JavaScript單線...
閱讀 3267·2023-04-26 02:10
閱讀 2888·2021-10-12 10:12
閱讀 4587·2021-09-27 13:35
閱讀 1528·2019-08-30 15:55
閱讀 1070·2019-08-29 18:37
閱讀 3433·2019-08-28 17:51
閱讀 1967·2019-08-26 13:30
閱讀 1203·2019-08-26 12:09