简体   繁体   中英

How to throw an error in an async generator function

Within an async generator function in Javascript, which is intended as a transform function, the first parameter is itself an async generator function. Within the function there is a conversion and a check. If the check is falsy, the generator function should be aborted. If the check is correct, the result should be yielded. I have simulated the error with the random.

I have found three ways to throw the error:

  • return Promise.reject(new Error("Some Message"));
  • throw new Error("Some Message.");
  • yield Promise.reject(new Error("Some Message"));
export async function* transformAsync<T>(
    source: AsyncGenerator<T, void, unknown>,
) {
    for await (const line of source) {

        const transformedLine = transformWithSomeMagic(line);

        if(Math.random() > 0.8) {
            return Promise.reject(new Error("Some Message"));
            // OR
            throw new Error("Some Message.");
            // OR
            yield Promise.reject(new Error("Some Message"));
        }

        yield transformedLine;
    }
}

The results are identical for all. I wonder where the difference is and if there are leaks when using streams as the source parameter, because they are compatible.

No matter wether you throw or return in a for..of loop, the iterator will be closed (no matter wether it is sync or async) [spec] .

Conceptually, the result of a further execution of an async generator is represented as a Promise, returning and yielding is like a resolution, and throwing is like a rejection. Now resolving a Promise with another Promise will "flatten" it, therefore the Promise.reject wrappers are superfluous. [spec]

        return Promise.reject(new Error("Some Message"));
        // barely equals
        resolve(Promise.reject(new Error("Some Message"))

        throw new Error("Some Message.");
        // barely equals
        reject(new Error("Some Message."));

        yield Promise.reject(new Error("Some Message"));
        // this one's more complicated, but it also barely equals
        resolve(Promise.reject(new Error("Some Message")));

Yes, they are all identical. There are no leaks, all of them also close the source iterator (calling .return() on it).

You should use the simple throw new Error(…); for explicitly throwing an error yourself, the other forms are useful when you are calling a promise-returning function and work as with an implicit await .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM