async/await
條件分歧必須改回callback寫法
code:javascript
promiseFn(1)
.then(res => {
console.log(res);
return promiseFn(0);
})
.then(res => {
console.log(res);
})
.catch(err => {
// 第一次 .then 失敗時,會略過第二次 .then,直接跳至此處
console.log(err);
});
code:javascript
async function example() {
const res1 = await promiseFn(1);
const res2 = await promiseFn(0);
// 失敗時會依 try catch 處理,若無則會直接中止
}
在內部使用try {} catch (error) {}攔截未預期行為或錯誤訊息
catch會連同reject與throw雙方的錯誤一同取得
呼叫帶有try {} catch (error) {}的函式時也必須帶有await
於function前加上async,回傳值會變為Promise
使用Promise或function回傳的Promise時,需加上await
code:javascript
async function getData() {
const data1 = await promiseFn(1);
const data2 = await promiseFn(2);
console.log(data1, data2);
}
getData();
await
只能用於async函式之中
用於接收值的時候
code:javascript
async () => {
await 3; // OK
console.log(response.text());
}
執行到await處時,會先一旦中斷處理,進入後方參數或函式內
直到取得後方參數的值後,才會繼續往下執行
code:javascript
// Case 1:
console.log(1);
(async() => {
console.log(2);
await new Promise(r => {
setTimeout(r, 1000);
console.log(3);
});
console.log(4);
})();
console.log(5);
// result: 1, 2, 3, 5, 4
// Case 2:
console.log(1);
(async() => {
console.log(2);
await 9;
console.log(3);
})();
console.log(4);
// result:1, 2, 4, 3
async/await並非為取代Promise,而是與Promise搭配運用
例如想要撰寫等待3秒鐘的函式,仍然需要用到Promise
code:javascript
const waitFor3Sec = () => {
return new Promise((resolve) => {
setTimeout(() => resolve("3 seconds"), 3000);
});
};
(async() => {
const result = await waitFor3Sec();
console.log(result);
})();
async對應的範圍只到同個括弧內
code:javascript
(async function() {
const res = arr.map(async x => await timerC(x));
console.log('end all', res);
})();
此例會先輸出end all [Promise, Promise, Promise]才接著內容
因為await對應到的是內側的async
為什麼要兩次await才能取得回應內容?
1. 避免回應內容太過巨大
2. 避免不會結束的串流回應
函式庫比較
語言比較
Rust
reqwest
Python
aiohttp
Go
net/http
https://www.youtube.com/watch?v=T-_0Pc5P12U
code:javascript
// 同步與非同步行為同時存在
// 1, 2, 3 如何輸出
const test = async () => {
console.log(1);
await setTimeout(() => {
console.log(2);
}, 1000);
};
const main = async () => {
await test();
console.log(3);
};
main();
// result: 1, 3, 2
// 修改為
const test = async () => {
console.log(1);
await new Promise((resolve) => {
setTimeout(() => {
console.log(2);
resolve();
}, 1000);
});
};
const main = async () => {
await test();
console.log(3);
};
main();
// result: 1, 2, 3
// 不使用 async/await
const test = () => {
console.log(1);
return new Promise((resolve) => {
setTimeout(() => {
console.log(2);
resolve();
}, 1000);
});
};
const main = () => {
test().then(() => {
console.log(3);
});
};
main();
// result: 1, 2, 3
code:async(javascript)
async function myFunc() {
const x = await doX();
const y = await doY(x);
return y;
}
const promise = myFunc();
code:generator(javascript)
function* myFunc() {
const x = yield doX();
const y = yield doY(x);
return y;
}
const promise = run(myFunc());
run()
code:run(javascript)
function run(comp) {
function onFulfilled(value) { // Promise成功時
let res;
try {
res = comp.next(value);
} catch (e) {
return Promise.reject(e); // throw
}
if (res.done) return Promise.resolve(res.value); //return
return res.value.then(onFulfilled, onRejected); // yield
}
function onRejected(error) { // Promise失敗時
let res;
try {
res = comp.throw(error);
} catch (e) {
return Promise.reject(e); // throw
}
if (res.done) return Promise.resolve(res.value); // return
return res.value.then(onFulfilled, onRejected); // yield
}
return onFulfilled();
}
型別問題
無法確保生成器的呼叫方式
無法對於每個yield加上不同型別