2016-08-24 118 views
2

我讀過Why do I have to use await for a method to run asynchronously. What if I don't want to wait for the method to finish before continuing?Are callbacks always asynchronous?,我仍然試圖瞭解何時回調實際上是異步的。爲什麼回調被認爲是異步的,如果我們需要等待

例如,doThat在做任何事情之前都需要等待GET數據。正如上面的第二個鏈接所述,javascript是單線程的。

doThis(doThat); 

function doThis(callback) { 
    $.get('http://some_api/some_resource', function (data) { 
     callback(data); 
    }); 
}; 

function doThat(data) { 
    // Do something with data 
}; 

只有我見過真正的異步功能與承諾,並承諾多在那裏我可以,例如,當動畫結束了加載其他數據。我希望能夠幫助我們更好地理解傳統回調是否實際上是異步的。具體的例子幫助。

+1

「回調」實際上只是一個函數,您將其作爲參數傳遞給另一個函數,以便其他函數可以調用它,這個進程* *可以*都是同步的 - 它實際上取決於其他函數功能在做。但即使在像Ajax這樣的異步情況下,它不是異步的回調函數本身,它最終會調用它是異步的。在你的例子中,'doThat()'不會等待 - 它是等待調用'doThat()'的其他代碼(你的'doThat()'定義也是無效的)。 – nnnnnn

+0

你可能想看看[所有的javascript回調是異步的嗎?如果不是,我怎麼知道哪些是?](http://stackoverflow.com/q/19083357/1048572)的一般問題和[什麼是異步JavaScript函數的簡單示例?](http:// stackoverflow.com/q/13806695/1048572)例如 – Bergi

+0

也許這有幫助嗎? http://stackoverflow.com/questions/21607692/understanding-the-event-loop – ecarrizo

回答

1

例如,我可以在動畫結束時加載其他數據。

這正是您可以對您的代碼執行的操作。請注意,您可以在等待doThat執行的同時運行其他代碼(實際上「運行其他代碼」會讓人感到困惑)。酷似動畫例如:

function doThis(callback) { 
    $.get('http://some_api/some_resource', function (data) { 
     callback(data); 
    }); 
}; 

function doThat(function (data) { 
    // Do something with data 
}); 

function doAnotherThing(function (data) { 
    // Do something with data 
}); 

doThis(doThat); 

// without waiting for doThat to run, you can IMMEDIATELY call: 
doThis(doAnotherThing); 

// without waiting for either doThat or doAnotherThing you 
// can output some pretty animations: 
setInterval(do_animation,100); 

// and without waiting for any of the above you can do anything else: 
document.body.innerHTML += 'hello'; 

注意什麼迷惑大多數人的是,document.body.innerHTML='hello'部分運行之前任何它上面的代碼。這意味着回調是異步的,因爲當數據到達時執行,而不是在調用該函數時。

請注意,並非所有的回調都是異步的。例如,Array.prototype.forEach()是同步的:

document.body.innerHTML += 'before<br>'; 
['hello','world'].forEach(function(x){ 
    document.body.innerHTML += x; 
}) 
document.body.innerHTML += '<br>after'; 

什麼決定天氣回調是異步或同步是調用它的函數。另請參閱:I know that callback function runs asynchronously, but why?

+0

這是一個明確的解釋。謝謝! – Growler

4

與定義開始:

不同步,在計算機編程,是指獨立於主程序流程和方法來處理此類事件的事件的發生。這些可能是「外部」事件,例如信號的到來,或者是與程序執行同時發生的程序引發的行爲,而不會阻止程序等待結果。

- Davies,Alex(2012)。在C#5.0中的異步,通過維基百科對Asynchrony (computer programming)

在JavaScript的情況下,它的工作原理是這樣的(簡化):有一個等待主線程(並且只有)執行的任務隊列。加載腳本時,它是放置在該隊列上的任務。一個任務運行直到它退出,並且其他任務都不會中斷它。但是,任務可能導致其他任務被放置在隊列中。當一個任務完成時,隊列上的下一個任務開始。如果隊列爲空,則後來進入隊列的第一個任務將立即執行。

的任務進入隊列,除了是腳本的主要任務主要方式來解析和執行:觸發事件將會把有關任務隊列事件註冊處理程序,並達到通過setTimeoutsetInterval預定時間將關聯的任務放置在任務隊列中。

在JavaScript方面,該相同任務(「主程序流程」)內執行的一切被說成是同步。在未來任務中執行的所有內容都稱爲異步。另一種說法是 - 如果下一條語句在回調之前執行,則它是異步的;如果下一條語句在回調後執行,則它是同步的。

$.get(opts, callback)是異步調用,因爲執行功能callback的任務將在onreadystatechange事件觸發時置於任務隊列中。如果你有一個後面的聲明,它會先執行;只有在任務完成後,由於AJAX調用更新而進入任務隊列的任務纔有機會運行。

相比之下,$.each(collection, callback)是一個同步調用,因爲callback將從each函數直接調用,而不必退出當前的任務,而不會自己反正產生任何額外任務(當然不是callback可以產生額外的任務)。下一個陳述將不得不等到each完成遍歷collection的每個元素。

請注意,承諾僅僅是對此機制的封裝。所有你可以用承諾做的事情,你可以在沒有它們的情況下做,只是代碼不會很漂亮和清晰。

相關問題