JavaScript:回調函數到底是什麼?

什麼是回調函數(Callback)

簡而言之:回調是要在另一個函數完成執行之後執行的函數,因此名稱爲“ call back”。

更復雜地說:在JavaScript中,函數是對象。 因此,函數可以將函數作爲參數,並且可以由其他函數返回。 執行此操作的函數稱爲高階函數。 作爲參數傳遞的任何函數都稱爲回調函數。

爲什麼我們需要回調?

出於一個非常重要的原因-JavaScript是一種事件驅動語言。這意味着JavaScript不會繼續等待響應,而是會在偵聽其他事件時繼續執行。讓我們看一個基本的例子:

function first(){
  console.log(1);
}
function second(){
  console.log(2);
}
first();
second();

如你所料,首先執行函數,然後執行第二函數,將以下內容記錄到控制檯:

// 1
// 2

到目前爲止一切都很好。

但是,如果函數包含無法立即執行的某些代碼怎麼辦? 例如,我們必須先發送請求然後等待響應的API請求? 爲了模擬此動作,將使用setTimeout,它是一個JavaScript函數,將在設置的時間後調用該函數。 我們將功能延遲500毫秒以模擬API請求。 我們的新代碼將如下所示:

function first(){
  // Simulate a code delay
  setTimeout( function(){
    console.log(1);
  }, 500 );
}
function second(){
  console.log(2);
}
first();
second();

現在瞭解setTimeout()的工作方式並不重要。重要的是,你看到我們把console.log(1)移到500毫秒延遲內。那麼,當我們調用函數時會發生什麼呢?

first();
second();
// 2
// 1

即使我們先調用了first()函數,我們在second()函數之後纔打印了它的結果。

這並不是說JavaScript沒有按照我們想要的順序執行我們的函數,而是JavaScript在繼續執行second()之前沒有等待first()的響應。

那爲什麼給你看這個呢?因爲你不能在一個函數後調用另一個另一個函數,而又希望它們以正確的順序執行。回調是一種確保某些代碼在其他代碼已經完成執行之前不會執行的方法。

創建一個回調函數

好了,話不多說,讓我們創建一個回調!

首先,打開您的Chrome開發者控制檯(Windows:Ctrl + Shift + J)(Mac:Cmd + Option + J),然後在控制檯中鍵入以下函數聲明:

function doHomework(subject) {
  alert(`Starting my ${subject} homework.`);
}

現在讓我們添加回調-作爲doHomework()函數中的最後一個參數,我們可以傳入回調。然後在對doHomework()的調用的第二個參數中定義回調函數。

function doHomework(subject, callback) {
  alert(`Starting my ${subject} homework.`);
  callback();
}

doHomework('math', function() {
  alert('Finished my homework');
});

可以看到,如果你在控制檯中輸入上述代碼,則會收到兩個alert:“starting homework”alert,然後是“finished homework”alert。

但是,並非總是必須在我們的函數調用中定義回調函數。它們可以在我們的代碼的其他地方定義,如下所示:

function doHomework(subject, callback) {
  alert(`Starting my ${subject} homework.`);
  callback();
}
function alertFinished(){
  alert('Finished my homework');
}
doHomework('math', alertFinished);

此示例的結果與前面的示例完全相同,但是設置略有不同。我們可以看到,在doHomework()函數調用期間,我們已將alertFinished函數定義作爲參數傳遞。

一個真實的例子

我們嘗試調用Twitter的API。 向API發出請求時,必須等待響應,然後才能對該響應採取行動。 這是真實回調的一個很好的例子。 請求長這樣:

T.get('search/tweets', params, function(err, data, response) {
  if(!err){
    // This is where the magic will happen
  } else {
    console.log(err);
  }
})

T.get意味着我們正在向Twitter發送獲取請求

此請求中包含三個參數:“ search / tweets”(這是我們的請求的路由),params(這是我們的搜索參數)和一個匿名函數(即我們的回調)。

回調在這裏很重要,因爲我們需要等待服務器的響應才能繼續執行代碼。 我們不知道我們的API請求是否會成功,因此在通過get請求將參數發送到search/tweets後,我們等待。 一旦Twitter響應後,將調用我們的回調函數。 Twitter會向我們發送錯誤(錯誤)對象或響應對象。 在回調函數中,我們可以使用if()語句來確定我們的請求是否成功,然後對新數據採取相應措施。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章