JS基礎——非同步回撥
前言
一個剛入前端的小菜,雖然以前看到過關於回撥的文章,但是呢,理解起來有點費勁啊。當時的腦海裡就一個概念。
回撥:大多出現在Ajax請求,用於處理收到的請求結果。
嘿嘿,當時真的就是這一個想法啊。現在真的入這行,而且這個概念也非常重要,用的地方太多太多,是時候把它撿起來好好理解一番。
當然,本文適合菜鳥,因為我是以一個菜鳥的思維去理解的。
回撥概念
理解一個新東西,很有必須去理解下它的概念,因為這是最簡潔明瞭,前人總結的。
A callback is a function that is passed as an argument to another function and is executed after its parent function has completed.
中文意思:回撥是一個函式被作為一個引數傳遞到另一個函式裡,在那個函式執行完後再執行。
有點繞,好,咱們說大白話。就是 B函式被作為引數傳遞到A函式裡,在A函式執行完後再執行B。
下面咱們看看程式碼怎麼實現回撥。
function A(callback){
console.log("I am A");
callback(); //呼叫該函式
}
function B(){
console.log("I am B");
}
A(B);
這應該是最最簡單的回調了,我想大家應該明白回撥的釋義了吧。
當然,這麼簡單的同步回撥程式碼是不會用的,現實中用都是相對比較複雜帶傳參。
回撥函式和非同步
一開始我被回撥
和非同步
有點搞暈了。還以為回撥就一定是非同步的呢。
其實不然,相信上面的A,B函式的例子我們已經明白,回撥並不一定就是非同步。他們自己並沒有直接關係。
下面我們可以理解下 同步回撥
和非同步回撥
(同步非同步我就不單獨講了,概念很簡單)。
同步回撥
就是上面的A B
函式例子,它們就是同步的回撥。
非同步回撥
因為js是單執行緒的,但是有很多情況的執行步驟(ajax請求遠端資料,IO等)是非常耗時的,如果一直單執行緒的堵塞下去會導致程式的等待時間過長頁面失去響應,影響使用者體驗了。
如何去解決這個問題呢,我們可以這麼想。耗時的我們都扔給非同步去做,做好了再通知下我們做完了,我們拿到資料繼續往下走。
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true); //第三個引數決定是否採用非同步的方式
xhr.send(data);
xhr.onreadystatechange = function(){
if(xhr.readystate === 4 && xhr.status === 200){
///xxxx
}
}
上面是一個程式碼,瀏覽器在發起一個ajax
請求,會單開一個執行緒去發起http請求,這樣的話就能把這個耗時的過程單獨去自己跑了,在這個執行緒的請求過程中,readystate
的值會有個變化的過程,每一次變化就觸發一次onreadystatechange
函式,進行判斷是否正確拿到返回結果。
非同步程式設計的實現
就我目前知道兩種 回撥函式
和 事件監聽
,其實看了阮神的 非同步程式設計的文章 和下面的評論之後得出的理解。下面咱們就看看這兩種非同步程式設計的方式吧。
回撥函式
假定有三個函式
f1()
f2()
f3()
但是,f1
執行很耗時,而 f2
需要在f1
執行完之後執行。
為了不影響 f3
的執行,我們可以把f2
寫成f1
的回撥函式。
//最原始的寫法-同步寫法
f1(); //耗時很長,嚴重堵塞
f2();
f3(); //導致f3執行受到影響
//改進版-非同步寫法
function f1(callback){
setTimeout(function () {
// f1的任務程式碼
callback();
}, 1000);
}
f1(f2); //
f3();
上面的寫法是利用 setTimeOut
把f1
的邏輯包括起來,實現javascript
中的非同步程式設計。這樣的話,f1非同步了,不再堵塞f3
的執行。
順道說下,js是單執行緒的,這裡所謂的非同步也是偽非同步,並不是開了多執行緒的非同步。它是什麼原理呢,其實是任務棧,setTimeOut
方法的原理是根據後面的定時時間,過了這個定時時間後,將f1
加入任務棧,注意僅僅是加入任務棧,並不是放進去就執行,而是根據任務棧裡的任務數量來確定的。
事件監聽
這裡我直接用阮神的例子,通過事件觸發操作,就是類似於咱們點選事件裡的處理邏輯。
同樣 f1 , f2
兩個函式。
f1()
f2()
f1
我們給它加一個事件,事件觸發 f2
函式。
function f1(){
setTimeOut(function(){
f1.trigger('click');
})
}
f1.on('click' , f2);
另外多說點,這上面的兩種方式都是 js
中的偽非同步,而 ajax
的非同步是底層多執行緒函式非同步。
寫在最後
由於時間問題,後續的理解會再補上,再理理思路。另外如果有錯誤,也請各位前輩給予指正,感激不盡。
參考文獻
感謝上面4篇文章的作者的辛勤付出,看完很有收穫。