0

I ran into a small dilemma. In this angularJs app (1.3.7v) I fetch requirements as well as user belongings from the server and perform some front-end validation. Which looks something like this:

validationFunction = function(userId){
  return new Promise(function(resolve, reject){
    Promise.all([
      requirementService.requirementApi.requirements.getAll().$promise,
      userBelongingsService.userBelongingsApi.getAll(userId).$promise
    ]).then(function(requirements,belongings){
      console.log(requirements, belongings);
      resolve(isValid(requirements,  belongings));
    }).catch(function (err) {
      reject(err);
    });
  });
}

For reference I also tried

validationFunction = function(userId){
  return new Promise(function(resolve, reject){
    requirementService.requirementApi.requirements.getAll().$promise.then(function(requirements) {
      return [requirements, userBelongingsService.userBelongingsApi.getAll(userId)];
    }).then(function(requirements,belongings){
      console.log(requirements, belongings);
      resolve(isValid(requirements,  belongings));
    }).catch(function (err) {
      reject(err);
    });
  });
}

The promises are async and so they only get resolved later. But if used with .then() it should wait until they are resolved (rejected or resolved). Although in both methods the promises are resolve(at some time) at the moment when they are passed to the function they are not. And so the function fails saying that they are undefined. So what is the other way or am I missing something? :)

MattJ
  • 683
  • 2
  • 10
  • 35
  • 1
    the success callback in `.then` accepts a single argument ... in the case of Promise.all, this argument will be an array of resolved values – Jaromanda X Sep 26 '16 at 10:27
  • in es2015 (maybe es2016) - you can `.then(function([requirements,belongings]){` to get what you want – Jaromanda X Sep 26 '16 at 10:30
  • not sure what the `resolve(isValid(requirements, belongings));` is meant to do, but perhaps you may just want to `return isValid(requirements, belongings);` - it's not clear from the code you posted as there's no wayof knowing what the `resolve` function even is – Jaromanda X Sep 26 '16 at 10:32
  • I included the wrapper this time :) – MattJ Sep 26 '16 at 10:43
  • your `validationFunction` doesn't return anything - perhaps you need to `return new Promise ...` - then read the other comments – Jaromanda X Sep 26 '16 at 10:44
  • Again sorry for the mistake :) did not copy it properly :) – MattJ Sep 26 '16 at 10:50
  • Avoid the [`Promise` constructor antipattern](http://stackoverflow.com/q/23803743/1048572)! – Bergi Sep 26 '16 at 11:56

1 Answers1

1

your code can be simplified to

validationFunction = function(userId){
    return Promise.all([
        requirementService.requirementApi.requirements.getAll().$promise,
        userBelongingsService.userBelongingsApi.getAll(userId).$promise
    ]).then(function([requirements,belongings]){
        console.log(requirements, belongings);
        return isValid(requirements,  belongings);
    });
};

However, that contains some es2015+ specifics

so, in less modern JS

validationFunction = function(userId){
    return Promise.all([
        requirementService.requirementApi.requirements.getAll().$promise,
        userBelongingsService.userBelongingsApi.getAll(userId).$promise
    ]).then(function(results){
        console.log(results[0], results[1]);
        return isValid(results[0], results[1]);
    });
};

edit: sorry, I missed a ) in the above code originally

To expand on the answer a little (got distracted with the real world) - Firstly, as @Bergi pointed out, Avoid the Promise constructor antipattern! - as you are dealing with functions that return a promise (Promise.all, ....getAll().$promise, ....getAll(userId).$promise) there's no need to wrap all that in a new Promise

Secondly, the onfulfilled callback of .then is called with a single argument, the resolved value. In the case of Promise.all, this is an array of resovled values, in the same order as they appear in the Promise.all argument. That's why the ES2015+ version can use the ([a, b]) form for the function argument (sorry, I can't recall or find the "name" for this form). It's important to note that if either one of those Promises in the Promise.all array are rejected, Promise.all rejects with the rejected value of the (first) rejected promise (that's a lot of rejection in that sentence!)

You can also remove the .catch portion of your code, as the error handling can (and should) be done by the calling code to your function

validationFunction(someUserId)
.then(function(result) {
     // this will be the value of isValid(requirements,  belongings)
})
.catch(function(err) {
    // do some error handling here
});

and finally, in it's most ES2015+ form (that I can think of)

validationFunction = userId => Promise.all([
    requirementService.requirementApi.requirements.getAll().$promise,
    userBelongingsService.userBelongingsApi.getAll(userId).$promise
]).then(([requirements, belongings]) => isValid(requirements, belongings));
Community
  • 1
  • 1
Jaromanda X
  • 53,868
  • 5
  • 73
  • 87