Pergunta

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.

Foi útil?

Solução 2

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.

Outras dicas

Is there any reason you're not making all requests at once?

self.user = getJSON("login");
self.contacts = getJSON("contacts");
self.companies = getJSON("companies");
// not sure what "/errors" does or what you assign it to, add it if you please

//.hash will go through object properties and wait for all promises to resolve
return RSVP.hash(self).then(function(results){
    //here, self now contains .user .contacts and .companies
    callback(self); //DO NOT do this, instead return the promise
}).catch(function(err){
     //this is where all error handling goes
});

Note the return there, it's best to return the promise rather than call a callback, you can .then it from the outside.

Similar to Benjamin Gruenbaum's, but slightly more concise.

return RSVP.hash({
  user: getJSON("login");
  contacts: getJSON("contacts");
  companies: getJSON("companies");
}}).then(callback).catch(function(err){
     //this is where all error handling goes
});
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top