邁入倒數五天,看來有些技術債是還不了了,但關於 Kotlin corouine
這個觀念還是要提一,讓我們開始吧!
介紹 coroutine
前先說明一下異步處裡,一般來說我們的程式碼是順序執行 (sequential execution),例如下面範例:
functionA()
functionB()
functionC()
結果就會是先執行 A -> B -> C
,乍看下沒有什麼問題,但假設函式 A 或是函式 B 內有呼叫需要等待較久回應的服務,例如:磁碟讀取、網路回應、使用者回應,那麼就會造成後面的函式被卡住並且主執行序當下是閒置狀態 (產生效能浪費、造成程序被標定為錯誤並回收…等)
在這樣的環境下,我們可以用回調函式 (callback function
) 解決這種問題,讓有延遲的函式在執行完成後再使用回調函式重新返回
fun postItem(item: Item) {
preparePostAsync { token ->
submitPostAsync(token, item) { post ->
processPost(post)
}
}
}
fun preparePostAsync(callback: (Token) -> Unit) {
// make request and return immediately
// arrange callback to be invoked later
}
(範例來在 Kotlin Official 文件 link)
延續上面的回調函式,如果我們有多個函式巢狀的包覆,那可讀性就會下降了 (波動拳RRRR)
於是異步處理這個構想就誕生了,下面範例借用 JavaScript 來說明 (誰說到異步處裡不會想到它呢 XD)。
// 沒有使用 async/await
fetchData(function(data) {
process(data, function(result) {
display(result, function() {
// 更多的嵌套回調...
});
});
});
// 使用 async/await
async function fetchDataAndDisplay() {
let data = await fetchData();
let result = await process(data);
await display(result);
// 代碼在這裡繼續執行,沒有縮排
}
範例中當函數執行到 await
時,它會等待 fetchData
函數完成,然後將結果賦值給 data
。接著,它等待 process(data)
完成,並將結果賦值給 result
。最後,它等待 display(result)
完成。
使用 async/await
的版本使得代碼看起來更像是同步的,減少了回調函數的嵌套,提高了可讀性。