同步的缺點是某一行如果需要比較多秒,畫面就會凍結,直到那一行執行完成。但 async 與 await 可以克服上面的麻煩,讓畫面不被凍結。讓我用同步的語法,背後卻是非同步的跑。
這個函式是非同步的,如果裡面要用 await,外面一定要用 async 包住。
const sleep = ms =>
new Promise( (resolve, reject) => setTimeout(resolve, ms))
async function main() {
console.log('enter main')
await sleep(500)
console.log('exit main')
}
main()
// 用 promise 的寫法
function mainPromise() {
console.log('enter main')
sleep(500).then(() => {
console.log('exit main')
})
}
await 後面接 promise 才會有 promise 的效果。它會等 promise 執行完畢才到下一行。
fetch 會把資料拿回來
const api200 = 'https://run.mocky.io/v3/c3eca63b-2cbd-4b74-bdab-ccc32767c7d0'
fetch(api200)
.then((response) => {
return response.json()
}).then(json => {
console.log(json)
}).catch(err => {
console.log('err', err)
})
簡化代碼,將 fetch 包成一個 function。fetch 會回傳一個 promise,所以我的 function 就直接 return 這個東西,故執行 function 就會拿到這個 fetch 的 promise。
function getData() {
const api200 = 'https://run.mocky.io/v3/c3eca63b-2cbd-4b74-bdab-ccc32767c7d0'
return fetch(api200)
.then((response) => {
return response.json()
})
}
下面可以接 .then() 拿到原本的資料
const request = getData()
request.then(data => {
console.log(data)
})
甚至也不用宣告變數,直接 getData().then
利用 await, async 看起來像同步的寫法去做非同步的事情。
function getData() {
const api200 = 'https://run.mocky.io/v3/c3eca63b-2cbd-4b74-bdab-ccc32767c7d0'
return fetch(api200)
.then((response) => {
return response.json()
})
}
async function main() {
console.log('enter main')
await(1000) // 等一秒,發 request 才秀結果
const result = await getData() // 等它,呼叫 function 拿到 promise
console.log('result', result) // 拿到 result {test: "okok"}
}
main()
利用這個寫法,錯誤處理就可以使用原本的 try catch
async function main() {
console.log('enter main')
await(1000) // 等一秒,發 request 才秀結果
try {
const result = await getData() // 等它,呼叫 function 拿到 promise
} catch(err) {
console.log('錯誤', err)
}
console.log('result', result) // 拿到 result {test: "okok"}
}
重點回顧
使用 async 與 await 可以用很像同步的方式寫代碼,但底層是非同步,可讀性大大提高,因為沒有甚麼 .then 或 .catch 的東西,就是基本的 function call。
唯一差別,這個 function call 會回傳一個 promise。要回傳 promise,才能用 async, await 語法達成這件事情。
getData return 是 undefined。
function getData() {
const api200 = '1https://run.mocky.io/v3/c3eca63b-2cbd-4b74-bdab-ccc32767c7d0'
fetch(api200) // 直接這樣沒有用,因為沒有回傳 promise。
.then((response) => {
return response.json()
})
}
async function main() {
console.log('enter main')
await(1000)
try {
const result = await getData() // getData 沒有回傳任何東西
console.log('result', result)
} catch(err) {
console.log('錯誤', err)
}
console.log('result', result) // 拿到 result {test: "okok"}
}
main()
.then 完 .cath 完 回傳的結果都是 promise,將 promise return 回去
function getData() {
const api200 = '1https://run.mocky.io/v3/c3eca63b-2cbd-4b74-bdab-ccc32767c7d0'
return fetch(api200)
.then((response) => {
return response.json()
})
}