同步 Sync 與非同步 Async
同步與非同步的差異
在學習同步與非同步的概念時很容易混淆,「同步」光看字面上的意思,可能會誤解成「所有動作同時進行」,而其實正好相反。
就以去夜市點餐來說明,如果今天想買的東西有:雞排、QQ球、珍奶。
同步 (sync):先去買雞排 -> 再去買QQ球 -> 然後再買珍奶。
像這樣「先完成 A 才能做 B、C、D …」的運作方式我們就會把它稱作「同步」。非同步 (async):再找兩個朋友幫忙,每人去一個攤位買一樣東西,就可以同時買好雞排、QQ球、珍奶。
所以同步的概念其實比較像是「一步一步來處理」的意思。
非同步則是,我不用等待 A 做完才做 B、C,而是這三個事情可以同時發送出去。
Promise
Promise 是 ES6 新增的建構函式,用來優化非同步的語法,增加可讀性。
Promise 字面上翻譯就是「約定、承諾」,可以想像成 A 和 B 約定要做某件事情,接著回報處理結果,而這個結果只能是「完成」或「拒絕」。
1 | function asyncFunction (value) { |
為什麼需要 Promise?
JavaScript 是單執行緒(同步)的程式語言,一次只能處理一件事情,所以遇到非同步的事件時,就會先把程式碼放到「事件佇列」,等到所有事件處理完後才會執行非同步事件。
1 | console.log('開始') // 執行順序 1 |
狀態
Promise 在處理非同步的事件的過程中,包含不同的進度狀態
- Pending:尚未得到結果
- Resolved:事件已經執行完畢且成功操作,回傳
resolve
的結果 - Rejected:事件已經執行完畢但操作失敗,回傳
reject
的結果
接收回傳
Promise 可以用 then
和 catch
來接收並回傳結果:then
可以同時接收成功、失敗結果,而 catch
只接收失敗結果
- 使用 catch 接收失敗:
在任何階段遇到reject
時,都會直接跳到catch
,之後的then
都不會執行
雖然catch
依然可以使用return
繼續串接,但很少這樣使用
1 | promise(1) |
- 使用 then 接收失敗:
then
中的兩個函式必定執行其中一個,可以用此方式確保所有的鏈接都能夠被執行
1 | promise(0) |
完成
- 最後可以使用
finally
來確認工作結束 finally
不帶有任何參數,適合用來確認 Ajax 已經讀取完成
1 | promise(1) |