【问题标题】:javascript break in for-await loop finish the generatorjavascript break in for-await 循环完成生成器
【发布时间】:2021-07-15 11:55:21
【问题描述】:

我编写了这段代码来迭代具有特定数字(如分页)的 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})。

为什么会完成,我怎样才能按预期完成这项工作?

【问题讨论】:

    标签: javascript generator for-await


    【解决方案1】:

    这是一个已知问题/功能,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()

    【讨论】:

    • 感谢您将我的回答标记为已接受,但是,不要急于这样做。这是一个有趣的问题,可能会吸引更多有能力的海报,看到你已经接受了这些海报会失去动力。让它保持“无人回答”至少几个小时。
    • 好的。顺便说一句,通过您的链接,我在参考文献中找到了这个:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 问题是在 for-await 循环的情况下我无法找到这个。
    猜你喜欢
    • 2019-02-25
    • 2018-11-24
    • 2018-06-15
    • 2018-05-07
    • 2017-07-11
    • 2022-01-04
    • 1970-01-01
    • 2021-08-26
    • 2015-04-01
    相关资源
    最近更新 更多