您説得對!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寫法

説明

function*

async function

聲明異步函數

yield

await

暫停執行等待Promise

runGenerator

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);
});

關鍵區別

  1. 語法糖
  • async/await是Generator+P執行器的語法糖
  • 不需要手動寫執行器
  1. 錯誤處理
// Generator版本
function* task() {
    try {
        const res = yield asyncOp();
    } catch(err) {
        // 處理錯誤
    }
}

// async/await版本
async function task() {
    try {
        const res = await asyncOp();
    } catch(err) {
        // 處理錯誤
    }
}
  1. 返回值
  • Generator函數返回迭代器
  • async函數返回Promise

歷史發展

  1. 回調地獄 → 2. Promise → 3. Generator → 4. async/await

Generator是JavaScript異步編程演進過程中的重要一步,它讓開發者可以用同步的方式寫異步代碼,最終演變成了更簡潔的async/await語法。