JS那些事兒——異步回調(diào)

前言

一個(gè)剛?cè)肭岸说男〔耍m然以前看到過(guò)關(guān)于回調(diào)的文章,但是呢,理解起來(lái)有點(diǎn)費(fèi)勁啊。當(dāng)時(shí)的腦海里就一個(gè)概念。

回調(diào):大多出現(xiàn)在Ajax請(qǐng)求,用于處理收到的請(qǐng)求結(jié)果。

嘿嘿,當(dāng)時(shí)真的就是這一個(gè)想法啊?,F(xiàn)在真的入這行,而且這個(gè)概念也非常重要,用的地方太多太多,是時(shí)候把它撿起來(lái)好好理解一番。

當(dāng)然,本文適合菜鳥(niǎo),因?yàn)槲沂且砸粋€(gè)菜鳥(niǎo)的思維去理解的。

回調(diào)概念

理解一個(gè)新東西,很有必須去理解下它的概念,因?yàn)檫@是最簡(jiǎn)潔明了,前人總結(jié)的。

A callback is a function that is passed as an argument to another function and is executed after its parent function has completed.

中文意思:回調(diào)是一個(gè)函數(shù)被作為一個(gè)參數(shù)傳遞到另一個(gè)函數(shù)里,在那個(gè)函數(shù)執(zhí)行完后再執(zhí)行。
有點(diǎn)繞,好,咱們說(shuō)大白話。就是 B函數(shù)被作為參數(shù)傳遞到A函數(shù)里,在A函數(shù)執(zhí)行完后再執(zhí)行B。

下面咱們看看代碼怎么實(shí)現(xiàn)回調(diào)。

function A(callback){
    console.log("I am A");
    callback();  //調(diào)用該函數(shù)
}

function B(){
   console.log("I am B");
}

A(B);

這應(yīng)該是最最簡(jiǎn)單的回調(diào)了,我想大家應(yīng)該明白回調(diào)的釋義了吧。
當(dāng)然,這么簡(jiǎn)單的同步回調(diào)代碼是不會(huì)用的,現(xiàn)實(shí)中用都是相對(duì)比較復(fù)雜帶傳參。

回調(diào)函數(shù)和異步

一開(kāi)始我被回調(diào)異步有點(diǎn)搞暈了。還以為回調(diào)就一定是異步的呢。
其實(shí)不然,相信上面的A,B函數(shù)的例子我們已經(jīng)明白,回調(diào)并不一定就是異步。他們自己并沒(méi)有直接關(guān)系。

下面我們可以理解下 同步回調(diào)異步回調(diào)(同步異步我就不單獨(dú)講了,概念很簡(jiǎn)單)。

同步回調(diào)

就是上面的A B函數(shù)例子,它們就是同步的回調(diào)。

異步回調(diào)

因?yàn)閖s是單線程的,但是有很多情況的執(zhí)行步驟(ajax請(qǐng)求遠(yuǎn)程數(shù)據(jù),IO等)是非常耗時(shí)的,如果一直單線程的堵塞下去會(huì)導(dǎo)致程序的等待時(shí)間過(guò)長(zhǎng)頁(yè)面失去響應(yīng),影響用戶體驗(yàn)了。

如何去解決這個(gè)問(wèn)題呢,我們可以這么想。耗時(shí)的我們都扔給異步去做,做好了再通知下我們做完了,我們拿到數(shù)據(jù)繼續(xù)往下走。

var xhr = new XMLHttpRequest();
    xhr.open('POST', url, true);   //第三個(gè)參數(shù)決定是否采用異步的方式
    xhr.send(data);
    xhr.onreadystatechange = function(){
        if(xhr.readystate === 4 && xhr.status === 200){
                ///xxxx
        }
    }

上面是一個(gè)代碼,瀏覽器在發(fā)起一個(gè)ajax請(qǐng)求,會(huì)單開(kāi)一個(gè)線程去發(fā)起http請(qǐng)求,這樣的話就能把這個(gè)耗時(shí)的過(guò)程單獨(dú)去自己跑了,在這個(gè)線程的請(qǐng)求過(guò)程中,readystate 的值會(huì)有個(gè)變化的過(guò)程,每一次變化就觸發(fā)一次onreadystatechange 函數(shù),進(jìn)行判斷是否正確拿到返回結(jié)果。

異步編程的實(shí)現(xiàn)

就我目前知道兩種 回調(diào)函數(shù)事件監(jiān)聽(tīng) ,其實(shí)看了阮神的 [異步編程的文章][2] 和下面的評(píng)論之后得出的理解。下面咱們就看看這兩種異步編程的方式吧。

回調(diào)函數(shù)

假定有三個(gè)函數(shù)

f1()

f2()

f3()

但是,f1執(zhí)行很耗時(shí),而 f2需要在f1執(zhí)行完之后執(zhí)行。
為了不影響 f3的執(zhí)行,我們可以把f2寫(xiě)成f1的回調(diào)函數(shù)。

//最原始的寫(xiě)法-同步寫(xiě)法

f1(); //耗時(shí)很長(zhǎng),嚴(yán)重堵塞
f2(); 
f3(); //導(dǎo)致f3執(zhí)行受到影響


//改進(jìn)版-異步寫(xiě)法
function f1(callback){
  setTimeout(function () {
    // f1的任務(wù)代碼
    callback();
  }, 1000);
}

f1(f2); //

f3();

上面的寫(xiě)法是利用 setTimeOutf1的邏輯包括起來(lái),實(shí)現(xiàn)javascript中的異步編程。這樣的話,f1異步了,不再堵塞f3的執(zhí)行。
順道說(shuō)下,js是單線程的,這里所謂的異步也是偽異步,并不是開(kāi)了多線程的異步。它是什么原理呢,其實(shí)是任務(wù)棧,setTimeOut方法的原理是根據(jù)后面的定時(shí)時(shí)間,過(guò)了這個(gè)定時(shí)時(shí)間后,將f1加入任務(wù)棧,注意僅僅是加入任務(wù)棧,并不是放進(jìn)去就執(zhí)行,而是根據(jù)任務(wù)棧里的任務(wù)數(shù)量來(lái)確定的。

事件監(jiān)聽(tīng)

這里我直接用阮神的例子,通過(guò)事件觸發(fā)操作,就是類似于咱們點(diǎn)擊事件里的處理邏輯。

同樣f1 , f2兩個(gè)函數(shù)。

f1()

f2()

f1 我們給它加一個(gè)事件,事件觸發(fā) f2 函數(shù)。


function f1(){
   setTimeOut(function(){
        f1.trigger('click');
    })
}

f1.on('click' , f2);

另外多說(shuō)點(diǎn),這上面的兩種方式都是 js 中的偽異步,而 ajax的異步是底層多線程函數(shù)異步。

寫(xiě)在最后

由于時(shí)間問(wèn)題,后續(xù)的理解會(huì)再補(bǔ)上,再理理思路。另外如果有錯(cuò)誤,也請(qǐng)各位前輩給予指正,感激不盡。

參考文獻(xiàn)

http://blog.csdn.net/kobejayandy/article/details/17654967
http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF%BC%BFjavascript.html
https://segmentfault.com/a/1190000002999668
https://segmentfault.com/a/1190000003961547

感謝上面4篇文章的作者的辛勤付出,看完很有收獲。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 弄懂js異步 講異步之前,我們必須掌握一個(gè)基礎(chǔ)知識(shí)-event-loop。 我們知道JavaScript的一大特點(diǎn)...
    DCbryant閱讀 2,879評(píng)論 0 5
  • 五十三:請(qǐng)解釋 JavaScript 中 this 是如何工作的。1.方法調(diào)用模式當(dāng)一個(gè)函數(shù)被保存為一個(gè)對(duì)象的屬性...
    Arno_z閱讀 683評(píng)論 0 2
  • 什么是同步異步 同步:當(dāng)我們發(fā)出了請(qǐng)求,并不會(huì)等待響應(yīng)結(jié)果,而是會(huì)繼續(xù)執(zhí)行后面的代碼,響應(yīng)結(jié)果的處理在之后的事件循...
    liwuwuzhi閱讀 510評(píng)論 1 1
  • 官方中文版原文鏈接 感謝社區(qū)中各位的大力支持,譯者再次奉上一點(diǎn)點(diǎn)福利:阿里云產(chǎn)品券,享受所有官網(wǎng)優(yōu)惠,并抽取幸運(yùn)大...
    HetfieldJoe閱讀 3,199評(píng)論 8 35
  • //Clojure入門(mén)教程: Clojure – Functional Programming for the J...
    葡萄喃喃囈語(yǔ)閱讀 4,043評(píng)論 0 7

友情鏈接更多精彩內(nèi)容