目錄
async & await
async、await是generator + Promise的語法糖
。因為不必再使用Promise chaining,更加提升
非同步函式的可讀性
async
帶有async 關鍵字的function非await的部分事實上還是同步
async function bar(){ console.log('bar'); } function foo(){ console.log('foo'); } bar(); foo(); // bar // foo
不管是否使用await,async function內的動作都會返回一個Promise物件
function wait(ms){ return new Promise(r => { setTimeout(r, ms); }) } async function foo(){ return 'foo'; // [[Prototype]]: Promise // [[PromiseState]]: "fulfilled" // [[PromiseResult]]: "foo" } async function bar(){ await wait(500); return 'bar'; // [[Prototype]]: Promise // [[PromiseState]]: "fulfilled" // [[PromiseResult]]: "bar" }
await
await 關鍵字可以讓
執行暫停,直到Promise被完成
The await keyword is for making the JavaScript function execution wait until a promise is settled
async function bar(){ console.log('bar'); // 執行到await就暫停,先去執行同步函式foo await fetch('https://api.github.com/orgs/tailwindcss') .then((d) => d.json()) .then(d => { console.log(d); }) console.log('barr'); } function foo(){ console.log('foo'); } bar(); foo(); // bar // foo // {login: 'tailwindcss', id: 30317862, node_id: 'MDEyOk9yZ2FuaXphdGlvbjMwMzE3ODYy', url: 'https://api.github.com/orgs/tailwindcss', repos_url: 'https://api.github.com/orgs/tailwindcss/repos', …} // barr
只能放在async function裡
function foo(){ await fetch('https://api.github.com/orgs/bootstrapvue') .then(d => d.json()) .then(d => console.log(d)) } // VM1289:2 Uncaught SyntaxError: await is only valid in async functions and the top level bodies of modules
迴圈執行非同步函式
用迴圈執行非同步函式,且想要迴圈完成後再執行下一個指令時,可能會想這樣寫,但這樣會先執行console.log('done')(因為是同步)
const urlArray = ['https://api.github.com/orgs/bootstrapvue', 'https://api.github.com/orgs/tailwindcss']; async function foo(arr){ arr.forEach(async i => { await fetch(i) .then(d => d.json()) .then(d => console.log(d)) }) console.log('done'); } foo(urlArray); // done // {login: 'tailwindcss', id: 30317862, node_id: 'MDEyOk9yZ2FuaXphdGlvbjMwMzE3ODYy', url: 'https://api.github.com/orgs/tailwindcss', repos_url: 'https://api.github.com/orgs/tailwindcss/repos', …} // {login: 'nodejs', id: 9950313, node_id: 'MDEyOk9yZ2FuaXphdGlvbjk5NTAzMTM=', url: 'https://api.github.com/orgs/nodejs', repos_url: 'https://api.github.com/orgs/nodejs/repos', …}
使用
for await...of
可以達到類似同步迭代的效果
,但一樣只能用於async function裡The for await...of statement creates a loop iterating over async iterable objects as well as on sync iterables, including: built-in String, Array, Array-like objects (e.g., arguments or NodeList), TypedArray, Map, Set, and user-defined async/sync iterables.
It invokes a custom iteration hook with statements to be executed for the value of each distinct property of the object. This statement can only be used inside an async function.
const urlArray = ['https://api.github.com/orgs/bootstrapvue', 'https://api.github.com/orgs/tailwindcss']; async function foo(arr){ for await(let i of arr){ await fetch(i) .then(d => d.json()) .then(d => console.log(d)) } console.log('done'); } foo(urlArray); // {login: 'tailwindcss', id: 30317862, node_id: 'MDEyOk9yZ2FuaXphdGlvbjMwMzE3ODYy', url: 'https://api.github.com/orgs/tailwindcss', repos_url: 'https://api.github.com/orgs/tailwindcss/repos', …} // {login: 'nodejs', id: 9950313, node_id: 'MDEyOk9yZ2FuaXphdGlvbjk5NTAzMTM=', url: 'https://api.github.com/orgs/nodejs', repos_url: 'https://api.github.com/orgs/nodejs/repos', …} // done
serial operation & parallel operation
function foo(packageName){ return fetch(`https://api.github.com/orgs/${packageName}`) .then(d => { console.log(`${packageName} done.`) return d.json(); }) } // 依序 async function series() { return [await foo('vuejs'), await foo('nodejs'), await foo('tailwindcss')]; } // 平行 async function parallel() { const vueInfo = foo('vuejs'); const tailwindInfo = foo('tailwindcss'); const nodeInfo = foo('nodejs'); // 先把Promise建立起來 return [await vueInfo, await tailwindInfo, await nodeInfo]; } await series(); await parallel();
🖊名詞解釋
名詞 | 解釋 | 其他 |
---|---|---|
settled | Promise已被完成,狀態不會再改變了 |
📖參考資料
async functions - make promise friendly
JavaScript async and await - in plain English, please