在底層C語言中,有一個非常重要而特別的概念,叫做“中斷”。用比喻來說,我正在寫着博客,突然我媽打個電話過來,我就離開了鍵盤去接電話了,然后寫博客就中斷了,我聊完電話回來再繼續寫。乍一聽似乎並沒有什么大不了的是吧,似乎沒什么好說的。那具體在程序中怎么表現的呢?一台電視正在放着節目,我用遙控器一按,它就不得不轉過來處理紅外遙控的信號,要不然微有差遲的話,遙控信號就過去了,也就遙控失靈了。只有處理了這個遙控,然后它才能再轉回去處理它的視頻和聲音。這就是中斷。
在JS中,也有一個非常重要而特別的概念,叫做“異步回調”。同樣用比喻來說,我給經理發了封郵件,不可能一直晾在這里干等他回郵件吧,於是我先做其它的事情,等看到郵件通知了,我再回來處理這份郵件,這就是回調。在網頁程序中,最常見的回調莫過於AJAX請求了,發出了一個請求,不能讓瀏覽器一直卡死在那里一動也不能動就等着服務器發數據回來吧,這種一收一發一般也要一兩秒鍾,如果是這種一卡一卡地估計就沒人想用了,所以現在瀏覽器中絕大多數都是使用回調。
“中斷”和“異步回調”有一個很相似的地方,那就是都是放下正在做的事情,先轉去做另外的事情,然后再回來處理。不同的是,“中斷”是被外界打斷現在做的事,緊急去處理了再回來繼續做,而這個緊急處理一般來說要盡量簡短、耗時非常少,比如前面的電視機總不能按一下遙控就黑屏靜音了半秒鍾吧,所以中斷函數會要求寫得盡量簡短。而“異步回調”則是,我知道我要等一會才能得到答復,所以我先做着其它事情的一種主動式的行為轉移,等得到答案了再回來處理原來的事情。據說NodeJS可接受的並發量很高,大概就是這個原因吧,數據庫反應不過來就讓它慢慢來,這些人都在我這里排着隊,排完一隊折回來又一隊。而其它后端一般是同步的,數據庫不夠用的時候,就像隊伍排到了門口但又不能折回來,后面來的就只能到大街上等吧。
說了這么一堆,那代碼是個什么樣子呢?下面這個就是一個典型的C51定時器中斷程序,可以看到它有 interrupt 和 3 作為標識它是一個中斷程序,序號為3。但其實還有非常重要的一點是,程序任何地方都不能調用這個函數,因為“中斷”是一個由外部因素(這里是定時器計數滿了)引發的一個行為,硬件機制會自動觸發這個函數執行,如果又允許其它程序調用那將會導致混亂。
//Timer1中斷服務程序 void time1Isr() interrupt 3{ //重裝數值 TH1 = (65536-92)/256; //定時100us TL1 = (65536-92)%256; //翻轉IO口電平 發聲 if (onBeep == 1){ beepC++; if (beepC >= 5){ beepC = 0; BuzzerIO =! BuzzerIO; //這里是電平翻轉哦,頻率快的話就能聽到聲音了 } } }
JS異步回調就常見了,就是把函數放在另一個函數的參數里。這,好像是類似於“函數指針”的東西?那是不是其它語言也可以在需要的時候使用這種“異步回調”的函數?
$.post("someURL", {key:"val", key2:"val2"}, function( result ){ console.log( result ); });