您説得對!Generator 的 yield 配合執行器確實可以模擬 await 的效果。讓我用一個更直觀的例子展示這種對應關係。
Generator 模擬 async/await
// 模擬異步函數
function delay(ms, value) {
return new Promise(resolve => setTimeout(() => resolve(value), ms));
}
// Generator函數(類似async函數)
function* asyncTask() {
console.log('開始任務');
const result1 = yield delay(1000, '第一步完成');
console.log(result1);
const result2 = yield delay(1500, '第二步完成');
console.log(result2);
return '任務完成';
}
// 執行器(類似await的底層實現)
function runGenerator(genFn) {
const iterator = genFn();
function handle(result) {
if (result.done) return Promise.resolve(result.value);
return Promise.resolve(result.value)
.then(res => handle(iterator.next(res)))
.catch(err => iterator.throw(err));
}
return handle(iterator.next());
}
// 執行Generator
runGenerator(asyncTask).then(finalResult => {
console.log('最終結果:', finalResult);
});
與async/await的對應關係
|
Generator寫法
|
async/await寫法
|
説明
|
|
|
|
聲明異步函數
|
|
|
|
暫停執行等待Promise
|
|
|
JavaScript引擎內置
|
自動執行器
|
轉換為async/await版本
// 同樣的異步函數
function delay(ms, value) {
return new Promise(resolve => setTimeout(() => resolve(value), ms));
}
// async/await版本
async function asyncTask() {
console.log('開始任務');
const result1 = await delay(1000, '第一步完成');
console.log(result1);
const result2 = await delay(1500, '第二步完成');
console.log(result2);
return '任務完成';
}
// 直接調用
asyncTask().then(finalResult => {
console.log('最終結果:', finalResult);
});
關鍵區別
- 語法糖:
- async/await是Generator+P執行器的語法糖
- 不需要手動寫執行器
- 錯誤處理:
// Generator版本
function* task() {
try {
const res = yield asyncOp();
} catch(err) {
// 處理錯誤
}
}
// async/await版本
async function task() {
try {
const res = await asyncOp();
} catch(err) {
// 處理錯誤
}
}
- 返回值:
- Generator函數返回迭代器
- async函數返回Promise
歷史發展
- 回調地獄 → 2. Promise → 3. Generator → 4. async/await
Generator是JavaScript異步編程演進過程中的重要一步,它讓開發者可以用同步的方式寫異步代碼,最終演變成了更簡潔的async/await語法。