Почему можно уступить, не решить обещание - PullRequest
0 голосов
/ 21 октября 2018

У меня есть следующий код:

object = {
    getPastEvents: () => Promise.resolve([1,2,3])
}

function* fetchPastEvents() {
    const values = yield object.getPastEvents()
    console.log(values)
}

const events = fetchPastEvents()
events.next()
events.next()

Теперь я хотел бы знать, как я могу создать функцию getPastEvents, которая возвращает определенный values.Прямо сейчас values - это undefined.Я думал, что yield может разрешить такое обещание, как async await.

Ответы [ 3 ]

0 голосов
/ 21 октября 2018

Я думал, что yield может разрешить обещание, например async await.

Нет, yield для , что дает функция генератора это означает, что он останавливает выполнение функции в этой точке, возвращает выражение с правой стороны вызывающей стороне .next() и затем принимает значение, переданное в следующем вызове .next(value), чтобы продолжить выполнение.Это как-то асинхронно, но не имеет ничего общего с async / await.Однако вы можете дать обещание и позвонить следующему .next(value), когда обещание разрешится:

 async function co(generator) {
   let iterator = generator();
   let done, value;
   do {
     ({ done, value } = iterator.next(await value);
   } while(!done);
   return value;
}

Можно использовать как:

 co(function* doAsync() {
   let result = yield somePromise();
   console.log(result);
});

, но я не знаю, как это может бытьполезно.

0 голосов
/ 21 октября 2018

Использование yield в генераторе не гарантирует ожидание, пока обещание не будет выполнено полностью.

Чтобы ваш пример работал, вы должны написать код для вызова следующего метода объекта, который реализует итеративный протокол.

function runGenerator(asyncGen) {
    const gen = asyncGen();
    let returnValue;

    (function iterate(value){
        returnValue = gen.next(value);

        if(!returnValue.done) {
            returnValue.value.then(iterate);
        }
    })();
}

const object = {
    getPastEvents: () => Promise.resolve([1,2,3])
};

runGenerator(function*() {
    const values = yield object.getPastEvents();
    console.log(values);
});

Обратите внимание, что это просто реализация, вам нужно проверить больше условий, если вы хотите использовать реальные проекты.

Вместо того, чтобы просто реализовывать свои собственные для этого, я бы рекомендовал использовать co module.


Обратите внимание, что Async & Await очень похож на этот подход, они оба требуют многообещающего API.

Однако для использования Async & Await, убедитесь, что ваш движок JavaScript поддерживает, иначе вам нужно выполнить конвейер, чтобы заставить их работать в старых движках.

Но использование генератора будет работать на большинстве современных движков JavaScript, это довольно старая спецификация (ES6).

Также, как правило, передача Async & Await создает много кода, который может быть проблемой, если вы хотите сохранить размер контента, такой же маленький, как possible.

Ключевое отличие ES6 Generator и ES7 Async & Await заключается в том, что ES6 Generator не может использовать «функцию стрелки», которая действительно критична в некоторых ситуациях (вы должны сохранить ссылку «this» где-то перед тем, как попасть в генератор.в контексте функции), однако асинхронная функция ES7 может сделать это.

Обратите внимание, что ES7 Async & Await - это просто синтаксический сахар обещающего API, а генератор ES6 - нет.

0 голосов
/ 21 октября 2018

Когда вы звоните .next, вы возобновляете запуск функции генератора.Если вы хотите возобновить его с определенным значением, вы передаете значение в .next.Поэтому, если вы хотите воспроизвести поведение redux-saga по разрешению обещаний, а затем возобновить работу генератора, вам нужно принять обещание, полученное при первом вызове .next, дождаться разрешения обещания, используя метод .then,и затем вызовите .next с разрешенным значением.

const object = {
  getPastEvents: () => Promise.resolve([1,2,3])
}

function* fetchPastEvents() {
  console.log("entry")
  const values = yield object.getPastEvents()
  console.log(values)
}

const iterator = fetchPastEvents()
const promise = iterator.next().value;
promise.then(val => iterator.next(val))

Я бы порекомендовал вам не делать это самостоятельно.Если это сага, как вы сказали, запустите ее через сагу-редукцию, и вы получите это поведение бесплатно.Или, как уже упоминали другие, библиотека co реализует аналогичную функциональность.

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