lcrazyl
lcrazyl

Reputation: 3

When practicing Promise in JS, the result is unexpected,

function sendOne() {
  return new Promise(function(resolve, reject) {
    QF.get("./data/1.json", {}, function(data) {
      if (data.error === 0) {
        resolve(data);
      } else {
        reject(data);
      }
    })
  })
}

function sendTwo() {
  return new Promise(function(resolve, reject) {
    QF.get("./data/2.json", {}, function(data) {
      if (data.error === 0) {
        resolve(data);
      } else {
        reject(data);
      }
    })
  })
}

function sendThree() {
  return new Promise(function(resolve, reject) {
    QF.get("./data/3.json", {}, function(data) {
      if (data.error === 0) {
        resolve(data);
      } else {
        reject(data);
      }
    })
  })
}

var p1 = sendOne();


p1
  .then(function(data) {
    console.log("Succeeded for the first time");
    return sendTwo();
  }, function(data) {
    console.log("Failed for the first time")

  })
  .then(function(data) {
    console.log("Succeeded the second time");
    return sendThree();
  }, function(data) {
    console.log("Failed the second time")

  })
  .then(function(data) {
    console.log("Succeeded the third time");
  }, function(data) {
    console.log("Failed for the third time")
  })

All three requests are wrong, and they should all output wrong results. Why is the second request successful? In my understanding, after the first request fails, it will be executed a second time, but it will also fail the second time. But the problem now is that it will succeed the second time

Upvotes: 0

Views: 67

Answers (2)

3limin4t0r
3limin4t0r

Reputation: 21110

p1 // <- promise is rejected, go to next rejected handler
  .then(function(data) {                    //   |
    // ...                                  //   |
  }, function(data) { // <-----------------------+
    console.log("Failed for the first time")
    // no errors, successful undefined return value, go to next fulfilled handler
  })                                        //   |
  .then(function(data) { // <--------------------+
    console.log("Succeeded the second time");
    return sendThree(); // <- promise is rejected, go to next rejected handler
  }, function(data) {                       //   |
    // ...                                  //   |
  })                                        //   |
  .then(function(data) {                    //   |
    // ...                                  //   |
  }, function(data) {  // <----------------------+
    console.log("Failed for the third time")
  })

If the reject handler doesn't throw an error or return rejected promise the result is considered a success, therefore the next .then() will trigger the fulfilled handler. If you want to keep the reject handler chain going you have to re-throw the exception.

p1 // <- promise is rejected, go to next rejected handler
  .then(function(data) {                       //   |
    // ...                                     //   |
  }, function(data) { // <--------------------------+
    console.log("Failed for the first time")
    throw data; // <- causes the current promise to be rejected, go to next rejected handler
  })                                           //   |
  .then(function(data) {                       //   |
    // ...                                     //   |
  }, function(data) { // <--------------------------+
    console.log("Failed the second time")
    throw data; // <- causes the current promise to be rejected, go to next rejected handler
  })                                           //   |
  .then(function(data) {                       //   |
    // ...                                     //   |
  }, function(data) { // <--------------------------+
    console.log("Failed for the third time")
  })

Instead of throw data you could also use return Promise.reject(data) depending on your preference.

Alternatively you could place a single rejected handler at the end.

p1 // <- promise is rejected, go to the next reject handler
  .then(function(data) {                           //   |
    console.log("Succeeded for the first time");   //   |
    return sendTwo();                              //   |
  })                                               //   |
  .then(function(data) {                           //   |
    console.log("Succeeded the second time");      //   |
    return sendThree();                            //   |
  })                                               //   |
  .then(function(data) {                           //   |
    console.log("Succeeded the third time");       //   |
  }, function(data) { // <------------------------------+
    console.log("One, two or three failed.")
  })

Upvotes: 1

deceze
deceze

Reputation: 521995

p1
  .then(function(data) {
    console.log("Succeeded for the first time");
    return sendTwo();
  }, function(data) {
    console.log("Failed for the first time")
  })
  .then(function(data) {
    console.log("Succeeded the second time");
    return sendThree();
  }, function(data) {
    console.log("Failed the second time")
  })

If p1 fails, the error handler console.log("Failed for the first time") is being executed. This has caught the failure and prevented it from propagating. That's what error handlers/.catch clauses are for in promise chains: to stop error propagation and allow the chain to continue. Which it then does with the next .then, which prints console.log("Succeeded the second time"), regardless of whether sendTwo() was even called or not.

Upvotes: 2

Related Questions