1

Im building a response back from the server using angular in order to show private messages. So far i have this code which works fine but it doesnt look like using promises the correct way, specially for handling errors. Im wondering how im suppose to handle nested promises in a case like this using best practices?

function listenMessageSend(data) {

var imData = {
  message: data.data.id,
  sender: currentUser().id,
  reciever: $scope.reciever
}

Im.create(imData).then(function(im) {
  Message.update(im.data.message, {im: im.data.id}).then(function(msg) {
    User.get(msg.data.im.sender).then(function(sender) {
      msg.data.im.sender = sender.data;
      User.get(msg.data.im.reciever).then(function(reciever) {
        msg.data.im.reciever = reciever.data;
      });   
    });
    if (msg.data.im.sender === currentUser().id || msg.data.im.reciever === currentUser().id) {
      $scope.messages.push(msg.data);
    }
  })
});

};
3
  • Are you sure this works fine? the if condition is evaluated before .sender and .receiver are set in the promise callbacks! Commented Apr 28, 2015 at 23:47
  • .sender and .reciever already exist when Message.update() so it works fine Commented Apr 28, 2015 at 23:52
  • yes, that might be, but they have the "old" values in the if condition, as if User.get is only executed later. Not sure whether you wanted that. You should consider moving the if-statement before the User.get(…) call so that it gets clear. Commented Apr 28, 2015 at 23:59

2 Answers 2

1

You could get sender data at the same time you are getting receiver data. You shouldn't nest two promises that are contextually independent as it'd result in poor user experience, because you're waiting the "sender" response ends to issue the request that gets the "receiver" data, while the browser could perfectly deal with the two requests at the same time.

You should issue the two requests at the same time and wait for both to deal with related data. Like this:

Im.create(imData).then(function(im) {
  Message.update(im.data.message, {im: im.data.id}).then(function(msg) {
    var senderGet = User.get(msg.data.im.sender).then(function(sender) {
      msg.data.im.sender = sender.data;
    });
    var receiverGet = User.get(msg.data.im.reciever).then(function(reciever) {
      msg.data.im.reciever = reciever.data;
    });
    $q.all([senderGet, receiverGet]).then(function() {
      if (msg.data.im.sender === currentUser().id || msg.data.im.reciever === currentUser().id) {
        $scope.messages.push(msg.data);
      } 
    });
  })
});

Or another option if you believe it's more readable:

Im.create(imData).then(function(im) {
  Message.update(im.data.message, {im: im.data.id}).then(function(msg) {
    var senderGet = User.get(msg.data.im.sender);
    var receiverGet = User.get(msg.data.im.reciever);
    $q.all([senderGet, receiverGet]).then(function(response) {
      msg.data.im.sender = response[0].data;
      msg.data.im.reciever = response[1].data;      
      if (msg.data.im.sender === currentUser().id || msg.data.im.reciever === currentUser().id) {
        $scope.messages.push(msg.data);
      } 
    });
  })
});
Sign up to request clarification or add additional context in comments.

1 Comment

Seems good. Would be better to deal with the callback hell i guess
0

The if must stay inside the deeper promisse, because It will be resolved lastly:

User.get(msg.data.im.sender).then(function(sender) {
  msg.data.im.sender = sender.data;
  User.get(msg.data.im.reciever).then(function(reciever) {
    msg.data.im.reciever = reciever.data;
    if (msg.data.im.sender === currentUser().id || msg.data.im.reciever === currentUser().id) {
      $scope.messages.push(msg.data);
    }
  });   
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.