1

i'm getting stuck on an asynchronous algorithm :

I've an array of mongoose models :

var allRefDatasSchemas = {
  RefAllotement: mongoose.model('RefAllotement', RefDataSchema),
  RefModeleConstructeur: mongoose.model('RefModeleConstructeur', RefDataSchema),
  RefTypeKit: mongoose.model('RefTypeKit', RefDataSchema),
  RefTypeUtilisation: mongoose.model('RefTypeUtilisation', RefDataSchema),
};

I'd like to grab all items of each collection and put them in an array or something like that. If I do that, the this keyword of the find callback doesn't refer to the current model, so impossible for me to know which model items belong to

var results = {};

for (var model in allRefDatasSchemas) {

  allRefDatasSchemas[model].find(function(err, data) {

    // I'd like to do something like that :
    // but this.modelName is null, because it isn't the model
    // on which the find is done.
    results[this.modelName] = data;

    // if I use "model" variable, it doesn't work, because asynchronous callback

  });

}

I've also tried async library without success, because I always return to the same issue : impossible to know which model execute the find query inside the callback. Idem in a then if I use promises.

Please help me :) How would you do that ?

EDIT model.find calls query.find, query.find calls mquery.find. In mquery.find, callback is called, by lost the this reference a that time : this._collection.find(conds, options, utils.tick(callback)); /EDIT

Etienne
  • 655
  • 3
  • 15
  • You can edit your own question to add information rather than post comments. I really don't understand why you would want to do this as surely you can model in a different way. But `async` series should work for you, except that is not the code you have posted. – Neil Lunn Jun 12 '14 at 13:39
  • Yes, I understand your question about the modeling : my goal is to load some refdata (data used in select inputs) at a time on a backbone client app (to follow [this pattern](http://ricostacruz.com/backbone-patterns/#bootstrapping_data) ) :) – Etienne Jun 12 '14 at 14:19

1 Answers1

3

Please check this code snippet, I have made a working sample of what you need. Please check comments in the code for better understanding.

Sample Working code similar to what you required. Another ref ques for using async with mongoose.

/*
 * Object to store all models
 */
var allRefDatasSchemas = {
  RefAllotement: mongoose.model('RefAllotement', RefDataSchema),
  RefModeleConstructeur: mongoose.model('RefModeleConstructeur', RefDataSchema),
  RefTypeKit: mongoose.model('RefTypeKit', RefDataSchema),
  RefTypeUtilisation: mongoose.model('RefTypeUtilisation', RefDataSchema),
};
/*
 * need an array to run all queries one by one in a definite order using async waterfall mwthod
 */
var arr = [];
for(each in allRefDatasSchemas) {
    arr.push(each);
}

/*
 * Callback function for initiation of waterfall
 */
var queue = [
    function(callback) {
        // pass the ref array and run first query by passing starting index - 0
        callback(null, arr, 0)
    }
];

/*
 * Object to store result of all queries
 */
var finalResult = {};

/*
 * Generic Callback function for every dynamic query
 */
var callbackFunc = function(prevModelData, currentIndex, callback) {
    allRefDatasSchemas[arr[currentIndex]].find(function(err, result) {
        if(err) {
            console.log(err)
        } else {

            // Your Query
            // 
            // I'd like to do something like that :
            // but this.modelName is null, because it isn't the model
            // on which the find is done.

            // arr[currentIndex] will point to 
            // RefAllotement, RefModeleConstructeur etc. as you required
            finalResult[arr[currentIndex]] = result

            // send current result to next interation if required or you can skip
            // and increment the currentIndex to call next query 
            callback(null, result, currentIndex + 1)
        }
    })
}

/*
 * Add callback function for every dynamic query
 */
for(each in allRefDatasSchemas) {
    queue.push(callbackFunc);
}

/*
 * Run all dynamic queries one by one using async.js waterfall method
 */
async.waterfall(queue, function (err, result) {
    // Final object with result of all the queries
    console.log('finish', finalResult)
});

output will be in this format

finish { RefAllotement:[
        // Result of RefAllotement query
    ],
    RefModeleConstructeur:[
        // Result of RefModeleConstructeur query
    ],
    RefTypeKit:[
        // Result of RefTypeKit query
    ],
  RefTypeUtilisation:[
        // Result of RefTypeUtilisation query
    ]
}
Community
  • 1
  • 1
Harpreet Singh
  • 2,651
  • 21
  • 31
  • Amazing ! The only thing I was missing was to create a second array with indexed model's names ! with it, I can know the modelName in the find callback (`finalResult[arr[currentIndex]] = result`). Thanks a lot for you clear response ! – Etienne Jun 13 '14 at 10:17
  • Thanks to you too, My first question accepted in StackOverflow – Harpreet Singh Jun 13 '14 at 11:02