skip to Main Content

this question i asked AI about it to rate my knowledge
my answer is
Resolved: A
Rejected: B
Resolved: C
, but when i ran it on nodejs runtime env and even browser it outputs
Resolved: A
Resolved: C
Rejected: B

function* generatorFunction() {
  yield Promise.resolve("A");
  yield Promise.reject("B");
  yield Promise.resolve("C");
}

const generator = generatorFunction();

for (const promise of generator) {
  promise
    .then((value) => console.log("Resolved:", value))
    .catch((error) => console.log("Rejected:", error));
}

2

Answers


  1. Your code is placing the catch handler on the promise returned from .then(), not the original promise. If you attach them both to the original promise, you get the sequence you expect:

    for (const promise of generator) {
      promise.then((value) => console.log("Resolved:", value));
      promise.catch((error) => console.log("Rejected:", error));
    }
    

    You’ll also get an unhandled rejection error from the first promise chain (the .then() chain. To deal with that, you can put a dummy catch on that one:

    for (const promise of generator) {
      promise.then((value) => console.log("Resolved:", value)).catch(_ => _);
      promise.catch((error) => console.log("Rejected:", error));
    }
    

    It’s a little clearer using await (well to me it is):

    (async () => {
    for (const promise of generator) {
      try {
        console.log("Resolved:", await promise);
      }
      catch(e) {
        console.log("Rejected:", e);
      }
    }})()
    

    edit — Bergi points out that the original problem could also be solved by assigning both the resolved handler and the rejection handler in the original .then() call:

    for (const promise of generator) {
      promise.then(
        (value) => console.log("Resolved:", value), // happy
        (error) => console.log("Rejected:", error)  // not happy
      );
    }
    
    Login or Signup to reply.
  2. Your .then() and .catch() calls are adding functions to the event loop. Each time your loop gets the generator further, a new Promise is either resolved or rejected, that is, a function is added to the event loop. But, since the .catch is chained to the .then, which is also a promise and adds a function to the event loop because of the catch as well. Therefore, the event loop reached the .then() of B first which added a function to the event loop and this second function is executed after the .then() functions of A and C. You can use the fact that you can pass the resolve handler as the first parameter and the reject handler as the second parameter to the .then() call to your advantage:

    function* generatorFunction() {
      yield Promise.resolve("A");
      yield Promise.reject("B");
      yield Promise.resolve("C");
    }
    
    const generator = generatorFunction();
    
    for (const promise of generator) {
      promise
        .then((value) => console.log("Resolved:", value), (error) => console.log("Rejected:", error));
    }
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search