Javascript асинхронные генераторы меняют тип получаемого значения? - PullRequest
0 голосов
/ 24 сентября 2019

Итак, у меня есть некоторый метод генератора, который получает данные, вызывая другой метод, который возвращает разбитые на страницы данные.Этот генератор выполняет итерацию по самому последнему буферу и yield s для каждого элемента, пока не останется больше извлекаемых данных.

async function* paginated_generator(source, opts = {}) {
    buffer = await source(opts)
    while (true) {
        for (let item of buffer.items) {
            yield item
        }
        if (!buffer.paging.next) {
            break
        }
        buffer = await source({ ...opts, next: buffer.paging.next })
    }
}

Метод, который он вызывает в этом случае, выглядит следующим образом и создаетновый Notification экземпляр для каждой части данных.

async notifications_paginated(opts = {}) {
    let Notification = require('./Notification')
    let instance = this || opts.instance

    let data = await paginated_data(`${instance.api}/news/my`, {
        limit: opts.limit || instance.paginated_size,
        key: 'news',
        prev: opts.prev,
        next: opts.next,
        headers: instance.headers
    })

    data.items = data.items.map((item) => new Notification(item))
    return data

}

Когда я получаю данные из этого метода напрямую или вставляю что-то вроде console.log(item.some_getter) в генератор, прежде чем он выдаст, я вижу, чтоОбъект является экземпляром класса Notification.Но если I await следующее значение из метода генератора, то данные, которые он выдает, не имеют доступа ни к одному из методов или методов получения, прикрепленных к объекту Notification.

Что меняется, когда эти данные возвращаются из генератора?

1 Ответ

2 голосов
/ 24 сентября 2019

Вы не используете асинхронный генератор правильно, но прежде чем мы это сделаем, давайте немного очистим реализацию:

async function* paginated_generator(source, opts = {}) {
    let buffer = await source(opts)

    while (true) {
        yield * buffer.items

        if (!buffer.paging.next) return

        buffer = await source({ ...opts, next: buffer.paging.next })
    }
}

Когда вы вызываете функцию асинхронного генератора, она возвращает объект асинхронного генератора, который реализует как асинхронный итератор, так и асинхронные итерируемые протоколы.

Существует несколько различий между синтаксисом и протоколами асинхронных и синхронных аналогов для функций генератора и протоколов итерации:

Вот как должно выглядеть ваше использование (вероятно) в зависимости от предоставленного вами контекста:

const Notification = require('./Notification')

async* notifications_paginated (opts = {}) {
    const instance = this || opts.instance
    const gen = paginated_data(`${instance.api}/news/my`, {
        limit: opts.limit || instance.paginated_size,
        key: 'news',
        prev: opts.prev,
        next: opts.next,
        headers: instance.headers
    })

    for await (const item of gen) {
        yield new Notification(item)
    }
}

Затем вы можете использовать notifications_paginated() в асинхронном режиме.повторяемый илиасинхронный итератор Notification объектов.

Если вы попытаетесь буферизовать все элементы в notifications_paginated() перед возвратом, то ваш API может также вообще не использовать разбиение на страницы, так как буферизация элементов отрицает цельв первую очередь, нумерация страниц.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...