2

I'm having a hard time trying to understand promises, I'm sure I need to use them for this but I don't know how and other answers don't help me at all.

I'd like to loop over an array, query all the results for each value of the array, then after calculating the average value for these results, add the average in an array. After every iterations, this array is sent as a response.

Here is my code which could help understand me here:

Parse.Cloud.define('getScorePeopleArray', function(request, response) {

    var peopleArray = request.params.peoplearray;
    var query = new Parse.Query("Scores");
    var resultat;
    var index, len;
    var resultarray = [];
    var people;

    for (index = 0, len = peopleArray.length; index < len; ++index) {
      people = peopleArray[index];
      query.equalTo("People",people);
      query.find({
        success: function(results) {
          var sum = 0;
          for (var i = 0; i < results.length; ++i) {
           sum += results[i].get("Score");
          }
          resultat = (sum / results.length)*5;
          if(!resultat){
            resultarray.push("null");
          }else{
            resultarray.push(resultat);
          }
        },
        error: function() {
          response.error("score lookup failed");
        }
    }).then();
  }
  response.success(resultarray);  
});

Of course response.success is not called when every queries are done, but as soon as possible (since queries are asynchronous if I'm right). I know I have to change it with promises, but I don't understand at all how this works.

Thanks a lot in advance !

Val_Apprem
  • 79
  • 8
  • Do any of [these](https://stackoverflow.com/search?q=%5Bparse.com%5D+Promise.when+%5Bpromise%5D) help you? – Bergi Mar 19 '15 at 20:01
  • I'll check that, thanks – Val_Apprem Mar 19 '15 at 20:25
  • Good suggested reading by @Bergi for promise concurrence generally. You should also check out Parse.Query.or() which also does a union on the results. http://parse.com/docs/js/api/symbols/Parse.Query.html#.or – danh Mar 19 '15 at 20:51

1 Answers1

12
var _ = require('underscore');

Parse.Cloud.define('getScorePeopleArray', function(request, response) {

 var peopleArray = request.params.peoplearray; // what is this an array of?
 var resultArray = [];

  return Parse.Promise.as().then(function() { // this just gets the ball rolling
    var promise = Parse.Promise.as(); // define a promise

    _.each(peopleArray, function(people) { // use underscore, its better :)
      promise = promise.then(function() { // each time this loops the promise gets reassigned to the function below

        var query = new Parse.Query("Scores");
        query.equalTo("People", people); // is this the right query syntax?
        return query.find().then(function(results) { // the code will wait (run async) before looping again knowing that this query (all parse queries) returns a promise. If there wasn't something returning a promise, it wouldn't wait.

          var sum = 0;
          for (var i = 0; i < results.length; i++) {
            sum += results[i].get("Score");
          }
          var resultat = (sum / results.length) * 5;

          if (!resultat){
            resultArray.push("null");
          } else {
            resultArray.push(resultat);
          }

          return Parse.Promise.as(); // the code will wait again for the above to complete because there is another promise returning here (this is just a default promise, but you could also run something like return object.save() which would also return a promise)

        }, function (error) {
          response.error("score lookup failed with error.code: " + error.code + " error.message: " + error.message);
        });
      }); // edit: missing these guys
    });
    return promise; // this will not be triggered until the whole loop above runs and all promises above are resolved

  }).then(function() {
    response.success(resultArray); // edit: changed to a capital A
  }, function (error) {
    response.error("script failed with error.code: " + error.code + " error.message: " + error.message);
  });
});
jameswilsterman
  • 156
  • 1
  • 6
  • That's awesome, thanks ! EDIT: I'll also check other's links to understand better how promises work, it looks really powerful – Val_Apprem Mar 20 '15 at 07:02
  • Forgot to answer your questions on comments: The array is an array of strings, the query syntax looks right (people in the query represents each object of the array right?) – Val_Apprem Mar 20 '15 at 07:17
  • Sorry for the third message in a row, but I have an error: Cannot call method 'then' of undefined. for these lines: "return Parse.Promise.as().then(function() {..." and ".then(function() { response.success(resultarray);..." I'm looking into it – Val_Apprem Mar 20 '15 at 07:43
  • Think I just fixed it. Was missing a closing }); Sorry about that. – jameswilsterman Mar 20 '15 at 13:52
  • Still not working for me : Failed with: ReferenceError: resultarray is not defined at main.js:77:22 at e (Parse.js:2:5101) at Parse.js:2:4651 at Array.forEach (native) at Object.x.each.x.forEach [as _arrayEach] (Parse.js:1:665) at c.extend.resolve (Parse.js:2:4602) at Parse.js:2:5181 at e (Parse.js:2:5101) at Parse.js:2:4651 at Array.forEach (native) I try to do it with just queries and cache policies to make it faster, so don't worry if it stays unsolved Here is the pastebin for you to get the right line numbers: http://pastebin.com/jKYc2v7c – Val_Apprem Mar 20 '15 at 14:25
  • Ah I think the problem was a typo: resultarray vs resultArray – jameswilsterman Mar 20 '15 at 23:08