简体   繁体   中英

Q.all and an array of promises don't seem to be working

I'm trying to use Q to do some work. I loop through and call a function which saves data to the database and returns a promise. Once those are done I need to do something else, but the Q.all finishes, although I can see each resolve being called. I've going nuts, any ideas?

The setup:

// save the divisions and then do the division checks
// data.divisions is an array of objects
var promises = [];
data.divisions.forEach(function(dd){
    var d = new grpl.division.Division(dd),
        p = d.save();
    promises.push(p);
});

Q.all(promises)
.then(function(){
    // do some other stuff here
    // this never actually gets called

}).fail(function(err){
    cb(err);
}).done();

And here's d.save()

Division.prototype.save = function(){
    var self = this
        d = Q.defer();

    getPool().getConnection(function(err, db){
        if(err){ d.reject(err); return false; }

        var fields = {
            division_id: self.division_id,
            season_id: self.season_id,
            title: self.title,
            cap: self.cap,
            display_order: self.display_order
        };

        db.query("INSERT INTO division SET ? ON DUPLICATE KEY UPDATE ?", [fields, fields], function(err, result) {
            if(err){ d.reject(err); return false; }
            d.resolve(true);// this does get resolved for each division
        });
    });

    return d.promise;
}

I have no clue what's wrong, but it just stops and doesnt appear to ever resolved my Q.all call.

UPDATE It appears that the initial call to save will function properly, but subsequent save calls appear to be resolving the same promise as the first call. I wrapped the body of the save code into a variable function which I called from save and its working but I'm not 100% sure why (prototypical inheritance is my fallback whenever JS really confuses me). Any explanations or better ways to do it?

Division.prototype.save = function(){
    var func = function(self){
        var d = Q.defer();

        d.promise.division_id = self.division_id;

        getPool().getConnection(function(err, db){
            if(err){ d.reject(err); return false; }

            var fields = {
                division_id: self.division_id,
                season_id: self.season_id,
                title: self.title,
                cap: self.cap,
                display_order: self.display_order
            };

            db.query("INSERT INTO division SET ? ON DUPLICATE KEY UPDATE ?", [fields, fields], function(err, result) {
                if(err){ d.reject(err); return false; }
                d.resolve(result);
            });
        });

        return d.promise;
    }

    return func(this);
}

Okay, your debugging comments solved the problem and made it clear what I was missing. It is an incredibly small typo, and is one of the reasons I'd recommend using something like JSHint on your code.

Division.prototype.save = function(){
    var self = this
        d = Q.defer();

Can you see it? I didn't until your comments made it very clear what was going wrong.

Division.prototype.save = function(){
    var self = this
                   ^
        d = Q.defer();

You are missing a , , so d is a global variable, instead of scoped within save , so every time you call .save() , you rewrite the global, and all of your attempts to resolve and reject will resolve the same global, instead of the defered for each save call.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM