2

Is it possible to write an asynchronous generator like the following:

function gen() {
  return async function * () {
    yield await ...
    yield await ...
    yield await ...
  }()
}

So one can use it like this, for example:

for (let val of await gen()) {
  ...
}

I can't really work out the semantics of this construction, how are async generators used in loops?

11
  • 3
    What are you trying to accomplish? What is your goal? Commented Jan 4, 2018 at 18:35
  • No currently not. However, maybe in the future. Commented Jan 4, 2018 at 18:36
  • 2
    github.com/tc39/proposal-async-iteration/blob/master/README.md Commented Jan 4, 2018 at 18:39
  • @ppovoski To iterate over a bunch of operations that would otherwise be blocking, e.g. fetch Commented Jan 4, 2018 at 18:40
  • 1
    Redux-saga manages to do this by having a runtime function that handles the iterators. If the yielded value from the iterator is a promise, it will not call .next() or .throw() on the iterator until the promise has completed. Commented Jan 4, 2018 at 18:41

1 Answer 1

1

Until the async iteration proposal is complete, you could take a page from the Redux-saga book (like Cory Danielson mentioned) and have an adapter function that does all the async/await stuff.

const later = async (delay, value) => {
    return new Promise(resolve => {
        setTimeout(() => resolve(value), delay);
    });
};

function* rangePromise() {
    for (let i = 2; i < 10; i++) {
        let nextValue = yield later(100, i);
        yield nextValue;
    }
}

const forEachAsyncAdapter = async (iterator, ...callbacks) => {
    try {
        let next = iterator.next();
        while (!next.done) {
            while (!next.done && next.value && next.value.then) {
                next = iterator.next(await next.value);
            }
            if (!next.done) {
                await callbacks.reduce(
                    async (nextValue, callback) => {
                        nextValue = await callback(await nextValue);
                        return nextValue;
                    },
                    Promise.resolve(next.value)
                );
                next = iterator.next();
            }
        }
    } finally {
        if (typeof iterator.return === 'function') {
            iterator.return();
        }
    }
};


forEachAsyncAdapter(
    rangePromise(),
    async i => { console.log(i); return Array(i).join('a'); },
    async s => { console.log(s); return s.toUpperCase(); },
    async s => { console.log(s); }
);

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.