3
\$\begingroup\$

I'm using Q to flatten out some callbacks in my unit tests and return a promise to mocha (which knows to wait until the promise is resolved before running the next test).

Originally I had this code:

it ('resetCount should cause the count to reset as if there were no documents yet.', function () {
    // Now save user and check if its _id is what nextCount said.
    user.save(function (err) {
        should.not.exists(err);
        user._id.should.eql(0);

        // Call nextCount to check the next number. Should be one.
        user.nextCount(function (err, count) {
            should.not.exists(err);
            count.should.eql(1);

            // Now reset the count.
            user.resetCount(function () {
                // Call nextCount again to check that the next count is reset. Should be zero.
                user.nextCount(function (err, count) {
                    should.not.exists(err);
                    count.should.eql(0);
                    done();
                });
            });
        });
    });
});

With Q I turned it into this:

it('resetCount should cause the count to reset as if there were no documents yet.', function () {
    var userSchema = new mongoose.Schema({
        name: String,
        dept: String
    });
    userSchema.plugin(autoIncrement.plugin, 'User');
    var User = db.model('User', userSchema);

    // Create user and save it.
    var user = new User({name: 'Charlie', dept: 'Support'});
    // Now save user and check if its _id is what nextCount said.
    q.nmcall(user, 'save')
        .then(function (user) {
            user._id.should.eql(0);
            return q.nmcall(user, 'nextCount');
        })
        .then(function (count) {
            count.should.eql(1);
            return q.nmcall(user, 'resetCount');
        })
        .then(q.nmcall(user, 'nextCount'))
        .then(function (count) {
            count.should.eql(0);
        }, function (err) {
            should.not.exists(err);
        });

});

I no longer have to call the done callback because of how mocha understands to wait for the promise to resolve. I am new to Q so I'm wondering if I've done things the most efficient way. It seemed like calling node-style mongoose methods with q.nmcall (alias for q.invoke) made the most sense. However, if you think you could write the same code better then please let me know where I can improve it.

\$\endgroup\$
3
\$\begingroup\$
.then(q.nmcall(user, 'nextCount'))

is wrong. The nextCount call does return a promise (and starts its execution right away), while then does expect a [callback] function. You'd rewrite it to

.then(function(result_of_resetcount) {
    return q.nmcall(user, 'nextCount');
})

or shorten it with nfbind/nbind:

.then(q.nbind(user.nextCount, user))
\$\endgroup\$
  • \$\begingroup\$ q.nmcall returns a promise as I understand it.. \$\endgroup\$ – konijn Jan 14 '14 at 15:20
  • \$\begingroup\$ Yes, it does, but you're not allowed to pass one to then. \$\endgroup\$ – Bergi Jan 14 '14 at 16:49
  • \$\begingroup\$ Understood, duh.. \$\endgroup\$ – konijn Jan 14 '14 at 16:53
  • \$\begingroup\$ @Marc-Andre: Typo I guess but am not sure. Thanks for spotting it! The difference between nbind and nfbind is just the handling of the this context. If the method doesn't care about its context, you might as well have used .then(q.nfbind(user.nextCount)) \$\endgroup\$ – Bergi Apr 11 '14 at 14:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.