2017-01-19 56 views
0

我對回調的理解有點問題。我在過去的2天裏讀了很多,我知道的是以下內容(如果我錯了,請糾正我):Javascript - 回調的優點

JavaScript是單線程語言,您可以編程同步和異步。 同步表示每個語句在執行之前等待先前的語句完成。這可能會導致麻煩,因爲例如,如果連接到數據庫需要很多時間,則前一個之後的語句必須等待。 最後這是非常糟糕的,這就是爲什麼在Javascript中編程異步更好,因爲異步代碼不必等待,代碼可以繼續運行,用戶不必等待。

要編程異步回調函數(高階函數)是必要的。

現在我已經嘗試了很多的教程的一個小例子程序等

function testCallback(a,callback){ 
    console.log('1.function and given parameter: '+a); 
    callback(10); 
}  

testCallback(5 , function(x){ 
    console.log("2.function and given parameter of 1. function: "+x); 
}); 

是嗎?輸出:

1.function and given parameter: 5 
2.function and given parameter of 1. function: 10 

我不明白,有什麼優點是這個代碼,因爲我認爲仍然可能導致陷入困境?如果「的console.log( '1.功能和....')有問題,回調(10)函數將甚至停止或不?

感謝您的幫助!

+1

「如果......有問題,回調函數會停下來?」 - 好的,如果代碼有問題並且沒有調用回調,那麼回調就不會被調用。但這並不是回調的目的,它們不是爲了繞過錯誤的代碼而工作的。正如你所說,Javascript是單線程的。如果你正在等待數據庫,那麼整個線程被阻塞,沒有其他事情可以發生。所以數據庫代碼通常是異步的,發生在後臺的某處,讓JS線程去做其他事情。準備就緒後,它會調用回調並在JS線程上繼續。這就是目的 – deceze

+0

回調不是構建異步代碼的唯一方式,它們只是提供了一種可能性,歷史上是第一種,也許是目前最廣泛採用的方式。然而,還有其他方法,即承諾和異步/等待周圍的糖。 –

回答

4

JavaScript是一單線程的語言......

不,事實並非如此。語言隻字未提線程。大多數環境給你佔全球環境中的單個線程,雖然(和您可以創建更多的瀏覽器,它通過互操作消息)NodeJS只提供一個線程,一些環境(如JDK上的Rhino或Nashorn)提供真正的多線程(以及所有優點可能涉及的麻煩)。

使用回調不會使代碼異步。舉個例子,你的例子不是異步的。試想一下:

function testCallback(a,callback){ 
 
    console.log('1.function and given parameter: '+a); 
 
    callback(10); 
 
}  
 

 
console.log("Before the call"); 
 
testCallback(5 , function(x){ 
 
    console.log("2.function and given parameter of 1. function: "+x); 
 
}); 
 
console.log("After the call");

說明爲什麼我們看不到After the call直到2.function and given parameter of 1. function: 10後。

function testCallback(a,callback){ 
 
    console.log('1.function and given parameter: '+a); 
 
    setTimeout(function() { // Using setTimeout 
 
     callback(10);   // to make this call 
 
    }, 0);     // asynchronous 
 
}  
 

 
console.log("Before the call"); 
 
testCallback(5 , function(x){ 
 
    console.log("2.function and given parameter of 1. function: "+x); 
 
}); 
 
console.log("After the call");

是否回調是同步調用或異步完全取決於你正在將其傳遞給該函數:如果回調是異步的,我們會看到之前它。例如,Array#sort所使用的回叫被同步調用,但setTimeout使用的回叫被異步調用。

要使代碼異步,它必須啓動一個操作,然後讓該操作完成後面的,觸發回調。 setTimeout可以做到這一點,就像ajax正確使用一樣,也可以做很多其他事情。


注意回調是目前你如何處理異步行爲(簡單的回調就像上面,或promise回調),但接下來的規範(ES2017)將定義built-in language semantics與asynchronousity在async形式處理不進行回調和await。如果你使用像Babel這樣的工具進行傳輸,你今天可以使用這種語法。

2

在JavaScript回調中可以同步或異步。同步回調可以有很多好處,但他們不會做任何事情來阻止您的代碼。

我認爲理解異步代碼是什麼以及爲什麼是有益的最好方法是瞭解Javascript實際如何評估代碼。我推薦這個視頻,它非常清楚地解釋了這個過程https://www.youtube.com/watch?v=8aGhZQkoFbQ

0

JavaScript回調函數是一個作爲參數傳遞給另一個JavaScript函數的函數。回調可以是同步的或異步的。簡單地傳遞函數作爲參數不會改變其當前行爲。

它的行爲可以通過調用它在一個事件監聽器或setTimeout函數內執行它的方法來改變。基本上,事件監聽器或setTimeout等是由webapi以異步方式處理的。如果回調函數在這些函數中,那麼當它們像激活按鈕(事件監聽器)或在setTimeout中聲明的時間一樣被激活時,這些函數會被webapi移動到隊列中。它們將從隊列移動到堆棧(如果堆棧爲空)並最終在堆棧上運行。

使用回調函數的主要優點是可以從下面的代碼中可以看出: -

var add = function(x,y) { 
    return x+y; 
} 

var multiply = function(x,y){ 
    return x*y; 
} 

var calculate = function(x,y,callback){ 
    return callback(x,y); 
} 

console.log(calculate(4,9,add));