首頁 > web前端 > js教程 > 主體

JavaScript的同步與非同步

黄舟
發布: 2017-02-07 14:38:23
原創
1056 人瀏覽過

在JavaScript的學習過程當中,同步與非同步是兩個讓人非常頭痛的概念,對於初學者來說尤其如此。簡單來說,當兩件或兩件以上的事情同時發生的時候,這就叫同步;當他們並非同時發生的時候,這就叫異步。

這兩個概念雖然看起來很簡單,但是實際理解起來卻需要花一番功夫。我們需要透過實際操作,來了解什麼情況是同步,什麼情況是非同步。

你可能認為,普通的JavaScript函數,都是同步的。當你在使用setTimeout()和AJAX的時候,你可能也會認為他們是同步的,是不是?如果我告訴你,這兩個函數在某些時候也可以非同步,你相信嗎?

要想解釋清楚原因,我們需要Mr X來幫忙。

場景1:Mr X嘗試使用同步性

條件:

  • 1 Mr X是一個能解決複雜問題的人,能夠執行任何被指派的任務。

  • 2 要和他聯繫,唯一的方式就是打電話。

  • 3 無論你遇到了什麼問題或是任務,要想找Mr X幫忙,你就要打電話給他。

  • 4 Mr X會給你提供回答,或是立刻完成任務,並且在完成之後通知你。

  • 5 在Mr X的幫助下,你完成了任務,然後出去看電影。

在這個過程中,你和Mr X完成的,就是同步溝通。

你提問的時候,他在聽;他給答案的時候,你也同時在聽。

JavaScript的同步與非同步

 場景2:Mr X不喜歡同步性

 由於Mr X的能力實在太高,越來越多的人開始找他尋求幫助。於是,你打電話給他的時候,卻老是佔線。你沒辦法向他提問,他更無法幫你回答問題。

那麼Mr X能如何應對這種情況?

  • 1 Mr X僱用一個助手Mr M,並且配備一台答錄機。

  • 2 Mr M的工作,就是聽答錄機上的留言,然後把問題總結出來交給Mr X。

  • 3 這樣一來,當你打電話給Mr X的時候,你所聽到的不再是佔線的忙音,而是把問題留在答錄機上,等待Mr X回電。

  • 4 在解答問其他人的問題之後,Mr X給你回電,告訴你解決方法。

 那麼問題來了,這個過程是同步溝通還是非同步溝通?

 可以說,兩者兼有。當你在答錄機留言的時候,Mr X並沒有在聽,所以這是非同步溝通。

 但是當他回電的時候,你們兩個之間進行的,就是同步溝通了。

 現在你應該已經理解溝通時的同步和非同步了。現在再來談談JavaScript的同步與非同步。

JavaScript – 一種非同步的程式語言

 當有人說JavaScript是一種非同步語言的時候,他的意思就是,整體來說,在使用JavaScript的時候,你需要對它進行留言,在給它打電話的時候,你聽到的不會是忙音。

 JavaScript中的函數呼叫從來都不是直接發生的,它們是透過訊息留言來完成的。

 JavaScript使用的是訊息佇列,新進來的訊息(或事件)被暫存在這裡。 event-loop不斷的對這些訊息進行處理,將它們發送到呼叫堆疊(call stack)中,在這裡,相應的訊息函數被堆積為用於執行的框架(函數的自變數和因變數)。

呼叫堆疊包含著第一個被呼叫的函數的框架,還有在這個函數之上透過巢狀呼叫被呼叫的其他函數的框架。

JavaScript的同步與非同步

 當一個訊息加入佇列,它會一直等待,直到呼叫堆疊中前邊的訊息框架被處理完成之後。前面的訊息被處理之後,event-loop會將其從佇列中移除,然後把目前訊息的對應框架加入到呼叫堆疊中。

 這個訊息再一次開始等待,指導呼叫堆疊清空了它的對應框架,然後被從佇列中移除。

看看下面的程式碼:

 function foo(){}function bar(){  foo();
}function baz(){  bar();
}
baz();
登入後複製

 這裡被運行的函數為baz(),位於程式碼段最後一行,它會作為一個訊息加入佇列中,當event-loop揀選了它的時候,呼叫堆疊在執行的過程中開始堆疊 baz(), bar(), 和 foo()的架構。

JavaScript的同步與非同步

 在函數的執行完畢之後,它們的框架會從呼叫堆疊中被移除出去,而訊息依然在佇列中等待,直到baz()在堆疊中被彈出。

JavaScript的同步與非同步


記住,JavaScript中的函數呼叫從來都不是直接完成的,而是透過訊息完成的。

 那些具體的非同步方法是怎麼回事?

目前為止,我已經接觸到了一些API,例如setTimeout()和AJAX,它們都被特別顯示為非同步方法。怎麼回事?

有一個非常重要的事情,那就是了解那些東西是同步發生,以及那些東西是異步發生的。在事件和event-loop的幫助下,JavaScript能夠對訊息進行非同步處理,但這並不意味著JavaScript裡的所有東西都是非同步的。

我之前說過,在呼叫堆疊清空對應框架之前,訊息是不會離開佇列的。舉個例子,就像是你沒拿到答案之前,是不會出去看電影的——這個時候發生的事情就是同步的:你站在那裡等著任務完成,親眼看到任務完成之後才會離開。

以上就是JavaScript的同步與非同步的內容,更多相關內容請關注PHP中文網(www.php.cn)!


相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!