Search code examples
javascriptrsvp.js

reject handling in promises


The following code returns an RSVP promise from each getJSON method:

  getJSON('/login')
  .then(getJSON('/errors').then(function(users) {
    self.user = users;
  }))
  .then(getJSON('contacts').then(function(contacts) {
    self.contacts = contacts;
  }))
  .then(getJSON('companies').then(function(companies) {
    self.companies = companies;
    callback(self);
  }, function(err){
    console.log('does not get here')  
  }));

My understanding of promises is obviously wrong, I don't want to provide an error callback for each then and instead I thought that the error would be forwarded on to the next available error callback in one of the subsequent then functions.

In the above code, the getJSON on line 2 will be rejected but it is not forwarded onto the error callback in the last then.

Do I have to provide an error callback for each then. This does not seem any different from callback hell.


Solution

  • I think you're chaining your promises in a wrong way. Your getJSONS are not executing in succession after the previous completes. When you call the first getJSON (getJSON('/login')), you are not passing two handlers to its then method. You are passing a new getJSON call. This means that, just after the call to getJSON finishes (but before the ajax call ends) you are executing the second getJSON (getJSON('/errors')). You are passing the resulting promise as the first argument of the then method of getJSON('/login'). By doing this, this promise will resolve or reject with the same value as getJSON('/errors'). Okay but...

    .then(getJSON('companies').then(function(companies) {
        self.companies = companies;
        callback(self);
      }, function(err){
        console.log('does not get here')  
      }));
    

    Here you are passing a new promise, the one returned by getJSON(companies) as the first argument of a then method. The promise to which this method belongs, when rejected, will try to call the function passed as the second argument ... but there's none! So, because getJSON('companies') does not reject, you don't receive an error. I've rewritten your chain:

    getJSON('/login').then(
      function(users) {
          self.user = users;
          return getJSON('/errors');
      }).then(function() {
          return getJSON('contacts')
      }).then(function(contacts) {
          self.contacts = contacts;
          return getJSON('companies');
      }).then(function(companies) {
          self.companies = companies;
          callback(self);
      }, function(err){
        console.log('does not get here')  
      });
    

    Now I think it should work fine. After a succesfull resolve of each promise, a function making a new getJSON request will execute, and it will return its promise. If any of them rejects, the rejection will pass through until a then with second argument is found, which happens at the end of the chain. The last function(err) will capture anything that went wrong before that point.