1

I'm having a bit of a strange problem.

I need to add objects to an array, and using the normal array.push(object) doesn't seem to work (nothing is pushed).

The pushes happen both inside and outside for-loops in parse.com queries.

I've tried some debugging, and console.log on all steps return the results as I expect.

My question is: Is there something I don't know about how parse.com queries work in connection to array.push, or maybe for-loops? Any help would be appreciated.

The particulars are entities (array) and entity (object).

I'd expect a result something like:

entities = [
    { url: '/first', changefreq: 'weekly', priority: 1.0 },
    { url: '/second', changefreq: 'monthly', priority: 0.9 },
    { url: '/third', changefreq: 'weekly', priority: 0.5 }
];

But I only get the very first push to appear in the array.

I've checked all the parse.com queries, and they do return the data I need and use in the example below.

My code:

module.exports = {
  getSitemap: function(callback) {
    "use strict";
    var Page = Parse.Object.extend('Page'),
      pageQuery = new Parse.Query(Page),
      Article = Parse.Object.extend('Article'),
      articleQuery = new Parse.Query(Article),
      Profile = Parse.Object.extend('Profile'),
      profileQuery = new Parse.Query(Profile),
      Category = Parse.Object.extend('Category'),
      categoryQuery = new Parse.Query(Category),
      entities = [],
      entity = {},
      i,
      sitemap;

    entity.url = '/';
    entity.changefreq = 'weekly';
    entity.priority = 1.0;
    entities.push(entity);
    entity = {};

    articleQuery.equalTo('published', true);
    articleQuery.select("permalink");
    articleQuery.find().then(function(results) {
      for (i = 0; i < results.length; i += 1) {
        entity.url = '/article/' + results[i].get('permalink');
        entity.changefreq = 'monthly';
        entity.priority = 0.9;
        entities.push(entity);
        entity = {};
      }
    }, function(error) {
      // do nothing
    });

    pageQuery.select("pagePermaLink");
    pageQuery.find().then(function(results) {
      for (i = 0; i < results.length; i += 1) {
        entity.url = '/page/' + results[i].get('pagePermaLink');
        entity.changefreq = 'monthly';
        entity.priority = 0.7;
        entities.push(entity);
        entity = {};
      }
    }, function(error) {
      // do nothing
    });

    profileQuery.select("objectId");
    profileQuery.find().then(function(results) {
      for (i = 0; i < results.length; i += 1) {
        entity.url = '/author/' + results[i].id;
        entity.changefreq = 'monthly';
        entity.priority = 0.6;
        entities.push(entity);
        entity = {};
      }
    }, function(error) {
      // do nothing
    });

    categoryQuery.select("categoryPermaLink");
    categoryQuery.find().then(function(results) {
      for (i = 0; i < results.length; i += 1) {
        entity.url = '/category/' + results[i].get('categoryPermaLink');
        entity.changefreq = 'weekly';
        entity.priority = 0.5;
        entities.push(entity);
        entity = {};
      }
    }, function(error) {
      // do nothing
    });

    sitemap = sm.createSitemap({
      hostname: 'http://brianemilius.com',
      cacheTime: 300000,
      urls: entities
    });
    sitemap.toXML(function(err, xml) {
      if (err) {
        callback({
          error: err
        });
      }
      callback(xml);
    });
  }
};

5
  • It might be helpful to read about JavaScript promises Commented Jan 31, 2016 at 17:48
  • I already did and found nothing that would explain my problem. Maybe you see something I don't? Commented Jan 31, 2016 at 17:51
  • Please console.log(results). in callback.Might be you not getting the data Commented Jan 31, 2016 at 18:06
  • As I wrote in the question I already did this debugging and I am getting the results I expect to get (from parse) on all steps. Commented Jan 31, 2016 at 18:09
  • Also results is not in the scope of the callback function, so it's not possible to log it there. This is one of the reasons I made an array (entities) in a parent scope, so I can transport data from one function to another. Commented Jan 31, 2016 at 18:24

1 Answer 1

2

The code is starting several asynch operations then immediately taking an action that relies on their results. We need to modify the code to wait until each operation is complete.

// ...
// above here from the OP 

articleQuery.equalTo('published', true);
articleQuery.select("permalink");
// hang on to the promise
var articlePromise = articleQuery.find().then(function(results) {
  for (i = 0; i < results.length; i += 1) {
    entity.url = '/article/' + results[i].get('permalink');
    entity.changefreq = 'monthly';
    entity.priority = 0.9;
    entities.push(entity);
    entity = {};
  }
}, function(error) {
  // do nothing
});

pageQuery.select("pagePermaLink");
// hang on to the promise
var pagePromise = pageQuery.find().then(function(results) {
  for (i = 0; i < results.length; i += 1) {
    entity.url = '/page/' + results[i].get('pagePermaLink');
    entity.changefreq = 'monthly';
    entity.priority = 0.7;
    entities.push(entity);
    entity = {};
  }
}, function(error) {
  // do nothing
});

profileQuery.select("objectId");
// hang on to the promise
var profilePromise = profileQuery.find().then(function(results) {
  for (i = 0; i < results.length; i += 1) {
    entity.url = '/author/' + results[i].id;
    entity.changefreq = 'monthly';
    entity.priority = 0.6;
    entities.push(entity);
    entity = {};
  }
}, function(error) {
  // do nothing
});

categoryQuery.select("categoryPermaLink");
// hang on to the promise
var categoryPromise = categoryQuery.find().then(function(results) {
  for (i = 0; i < results.length; i += 1) {
    entity.url = '/category/' + results[i].get('categoryPermaLink');
    entity.changefreq = 'weekly';
    entity.priority = 0.5;
    entities.push(entity);
    entity = {};
  }
}, function(error) {
  // do nothing
});

// only after all of the promises that create entities are fulfilled
// do we execute the logic that relies on that data

var promises = [articlePromise, pagePromise, profilePromise, categoryPromise];
Parse.Promise.when(promises).then(function() {
    sitemap = sm.createSitemap({
      hostname: 'http://brianemilius.com',
      cacheTime: 300000,
      urls: entities
    });
    sitemap.toXML(function(err, xml) {
      if (err) {
        callback({
          error: err
        });
      }
      callback(xml);
    });
}, function(error) {
    // handle error
});
1
  • This did exactly what I wanted. Thanks a bunch! Commented Feb 1, 2016 at 16:09

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.