Is it possible to use Async Generators with the ES5 syntax?

Asked

Viewed 110 times

4

For example, the code below that creates a async Generator:

async function* iterate() {
    yield 1;
    yield 2;
    yield 3;
    return null;
}

Could be used with the syntax for await...of:

for await (const iteration of iterate()) {
    console.log(iteration); // 1, 2, 3
}

The code that generates the iterator is from a library that uses Typescript, so it can be easily transposed into other versions of Ecmascript. But I want to use this third-party code without needing a transpilation process, maintaining compatibility with older browsers, how to use this code with ES5 syntax?

I made a test transpiring both this function and the loop that uses it, but a complex code is used with the help of various functions, making it difficult to understand and maintain

2 answers

0

Is it possible? Is it. Is it feasible? No. Basically, you have to create you a function that is the awaiter and another one that is the Generator and then flames one inside the other with the final callback being what you want to make it happen.

Is not nothingness simple. And I can’t figure out what you’d get out of it, when you can just do the code on ES6 and tell transpiler to get you the browser version that doesn’t support that javascript version

Alternatively, use polyfills for this; both the core-js like the async-polyfill can help.

  • Could you exemplify? Depending on the project, adding a build step is not worth it, it would add unnecessary complexity. It may also be that the code you are going to use is from a legacy project that doesn’t even have a possible way to add transpilation

  • 1

    @Costamilam if adding a build step is an unnecessary complexity, so you’ll have to wonder what gain you have in keep up a function that returns generators and awaiters. But the real question is: why is that what you’re doing nay supports this version of javascript? is that if it is a browser, it is a very old browser. If it’s nodejs -- why don’t you just upgrade to a version that supports es6 ? any solution will be better than making the generators and awaiters by hand.

  • You assume that other solutions are simple, but they are not always, even in updating Node, which is in an environment that theoretically you have control, can generate many problems. ES6 does not have compatibility for Opera mini and partial for IE (generators, for example, do not have support) even in the latest versions, although they are little used browsers, they are still used, and compatibility is important

  • 1

    I am not starting from the principle that all are simple, I simply look at the problem from a point of view of work that gives me to keep it in the future: Making a build step is stupidly easy when compared to making and maintaining generators and yields by resorting to old-fashioned promises -- it’s crazy. is doable? sure! but I abhor the days when I had to do it. However, and I forgot that, you can always turn to polyfills that already exist which I normally use when this rare problem appears. I edited the answer to reflect this.

0


  • It is possible, simply, through recursion instead of using a loop. I created the function asyncForeach, that receives an iterator and a callback function that will be executed at the end of each promise, at that point, just call the function again if that iterator has not finished

async function* iterate() {
    yield new Promise(resolve => setTimeout(resolve, 1000, 1));
    yield new Promise(resolve => setTimeout(resolve, 1000, 2));;
    yield new Promise(resolve => setTimeout(resolve, 1000, 3));;
    return null;
}

function asyncForeach(iterator, callback) {
    iterator.next().then(function(cursor) {
        if (!cursor.done) {
            callback(cursor.value)

            asyncForeach(iterator, callback);
        }
    });
}

asyncForeach(iterate(), console.log);

console.log('finish');

However, its function is slightly different from the syntax for await...of:

(async () => {
    async function* iterate() {
        yield new Promise(resolve => setTimeout(resolve, 1000, 1));
        yield new Promise(resolve => setTimeout(resolve, 1000, 2));
        yield new Promise(resolve => setTimeout(resolve, 1000, 3));
        return null;
    }

    for await (const iteration of iterate())
        console.log(iteration);

    console.log('finish');
})();

  • You can also create something similar using the ES6 syntax and transpose to an earlier version using any online playground with Typescript, Babel, Rollup or similar, and copy the result into your code:
function asyncForeach(iterator, callback) {
    for await (const iteration of iterator)
        callback(iteration);
}

So it is not necessary to add a build process, but to update this code, it would take a certain rework when tidying the settings, although this piece of code will hardly need maintenance, since it is something very simple that can use any iterator

  • If feasible and advantageous, a build process can be added to just that piece of code, but it’s not always

  • Another option is to use the ES6 syntax and only transpose the required code at runtime, but this is not recommended, since the same process will be repeated several times to each page re-load unnecessarily

  • Finally, it would use some utility library that has a function like the one above and is compatible with ES5, but I don’t know any

Browser other questions tagged

You are not signed in. Login or sign up in order to post.