You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用generators与Promise模拟async/await时输出pending Promise如何解决

基于Generator与Promise手动实现async/await核心逻辑

背景

学习生成器相关知识时,希望不直接使用async/await语法,通过生成器结合Promise模拟异步请求逻辑,手动实现async/await的核心原理。

首次尝试代码及问题

首次编写的代码运行后控制台始终打印pending状态的Promise,代码如下:

function* awaitReq() {
    const val1 =  
        new Promise((resolve, reject) => {
            setTimeout(() => resolve(5))
        }).then((val) => val )
        .catch((err) => "Error");
    
    yield val1;

    // second call
    yield val1 * 2;

}

const generator = awaitReq();
const { value, done } = generator.next();
// check if val is a number or error
if(isNaN(value)) {
    console.log(value)
    return value;
}
// otherwise, return the setTimeOut response times 2
console.log(generator.next().value)

问题分析

  • 第一次yield返回的是Promise实例本身,代码没有等待Promise状态变更就直接做isNaN判断,此时value为pending状态的Promise,判断永远为真,无法进入后续逻辑
  • val1本身是Promise对象,不能直接参与val1 * 2这类算术运算,即使拿到异步结果也会得到NaN
  • 缺少自动推进生成器执行的逻辑,手动调用next的时机早于异步任务完成时间,无法拿到预期结果

可行实现方案

调整后可正常运行的实现代码如下:

function getNumber() {
    return new Promise((resolve, reject) => {
        resolve(10);
    }).then((val) => {
        return new Promise((resolve, reject) => {
            resolve(val * 2)
            //reject("Error");
        }).then((val2) => val2);
    }).catch((err) => {
        return err;
    })
}

// 接收生成器函数作为参数
function run(generatorFn) {
    const iterator = generatorFn();     // 创建迭代器实例

    const handleNext = (value) => {
        const next = iterator.next(value);
        if(next.done) {
            return next.value;
        } else {
            return Promise.resolve(next.value)
                .then((val) => handleNext(val))
                .catch((err) => handleNext(err));
        }
    }

    handleNext();
}

run(function* () {
    try {
        const result = yield getNumber();
        console.log(result);
    } catch (ex) {
        console.log('Error: ' + ex);
    }
})

核心逻辑说明

  • run函数是async/await语法糖的核心实现:接收生成器函数作为入参,生成对应的迭代器实例
  • handleNext函数负责自动推进迭代器执行:每次拿到yield返回的值后,统一封装为Promise,等待Promise状态敲定后,将结果作为参数传入iterator.next,注入到生成器内部作为yield表达式的返回值,再递归推进下一次迭代,直到迭代器完成
  • 原生支持错误处理:如果yield返回的Promise触发reject,错误会被传入迭代器,可被生成器内部的try/catch捕获,表现和原生async/await一致

内容的提问来源于stack exchange,提问作者myTest532 myTest532

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 16:12:00