javascript break in for-await 循环完成生成器

标签 javascript generator for-await

我编写了这段代码来迭代具有特定数字(如分页)的 github 问题,在这种情况下,一次有 3 个问题:

const getUrl = (page) => `https://api.github.com/repos/angular/angular/issues?page=${page}`;

const getIssues = async function*() {
    for (let p = 1; true; p++) {
        const url = getUrl(p);
        const rawData = await fetch(url, {
            headers: { 'User-Agent': 'app' }
        });
        const issues = await rawData.json();
        for (let issue of issues) {
            yield issue;
        }
    }
};

const generator = getIssues();

document.querySelector('[data-next]').addEventListener('click', async function() {
    let i = 0;
    for await (let issue of generator) {
        console.log(issue);
        if (++i === 3) break;
    }
    console.log(await generator.next());
});
具有 data-next 属性的元素是一个按钮。预期的行为是每次单击按钮都会加载接下来的 3 个问题。问题是,生成器在中断后完成(console.log 打印:{value: undefined, done: true})。
为什么它完成了,我怎样才能按预期完成这项工作?

最佳答案

这是一个已知问题/功能,for..of终止生成器(参见例如 here )。一种可能的解决方案是提供一个代理,它将实际的生成器状态保存在一个闭包中:

function persist(gen) {
    return {
        next() {
            return gen.next()
        },
        [Symbol.asyncIterator]() {
            return this
        },
        [Symbol.iterator]() {
            return this
        }
    }
}

//

const getUrl = (page) => `https://jsonplaceholder.typicode.com/posts/${page}/comments`;

const getIssues = async function* () {
    for (let p = 1; true; p++) {
        const url = getUrl(p)
        const raw = await fetch(url)
        const data = await raw.json()
        yield* data
    }
};

async function main() {

    const generator = persist(getIssues());
    let i = 0;

    for await (let x of generator) {
        console.log(i, x.postId, x.id, x.name);
        if (++i === 4) break;
    }

    console.log('break'); i = 0;

    for await (let x of generator) {
        console.log(i, x.postId, x.id, x.name);
        if (++i === 4) break;
    }

    console.log('break'); i = 0;

    for await (let x of generator) {
        console.log(i, x.postId, x.id, x.name);
        if (++i === 4) break;
    }

}

main()

关于javascript break in for-await 循环完成生成器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67193277/

相关文章:

javascript - ASP.net 3.5 将现有网站转换为响应式设计

javascript - 如何在php中使用AJAX实现reCAPTCHA发送邮件?

python - 将成对生成器变成一对生成器

javascript - 错误 : [$injector:modulerr] with angular JS [GULP CONTEXT]

php - JQuery 在 IE 8 或 7 中不起作用

python - 如何解释Python中的timeit命令

python - 使用 scapy 灵活生成流量

javascript - 脱糖等待..的

javascript - VS Promise.all 的等待