How to make synchronous call with mongoose and nodejs
Asked Answered
D

1

7

I'm designing a client/server synchronization feature. The client sends a bunch of changed events to server. The server will do creation, deletion or modification upon requested item status. After the database operation, the server need send a summary back to client.

Below is excerpt from my server side code, designed with mongoose and restify.

var EventModel = mongoose.model('Event', eventSchema);
server.post("/sync", function (req, res, next) {
    var events = req.params.events;
    var created = [], deleted = [], updated = [];
    events.forEach(function (elem) {
        if (elem.status == 0) {
            // Delete
            EventModel.remove({ _id: elem.uuid }, function (err, event) {
                if (!err) deleted.push({uuid: elem.uuid});
            });
        } else if (elem.status == 1) {
            // Create and update uuid
            var event = new EventModel(elem);
            event.save(function (err, doc) {
                if (!err) {
                    elem.uuid = event._doc._id;
                    created.push(elem);
                }
            });
        } else if (elem.status == 2) {
              // Update
            EventModel.findOne({ _id: elem.uuid }, function (err, event) {
                event.save(function (err, doc) {
                    if (!err) updated.push({uuid:elem.uuid});
                });
            });
        }
    });
    // Notify client what are processed.
    // PROBLEM: created, deleted, updated are always empty!
    res.send({processed: {created: created, deleted: deleted, updated: updated}});
});

Since mongoose do CRUD in async way, the response created,deleted and updated are always empty. Is there any way to let the mongoose operation in series?

Dharma answered 2/7, 2014 at 16:46 Comment(6)
You need to learn how to write asynchronous code. In particular, look at async.forEach, which will handle the callbacks for you and let you run after everything has finished.Prospectus
Check this link - #17181748Thornburg
one more - #24185867Thornburg
I want to know, which link works for you (first or second)?.Thornburg
Your two posts provide the same idea, using async.waterfall. The latter link #24185867 is much clearer.Dharma
Possible duplicate of Make a blocking call to a function in Node.js required in this case?Chimborazo
D
1

As stated in the comments you could use the npm async module.

Alternatively, you may prefer to nest callbacks (but this might lead to what is known as callback hell, viz many nested callbacks) or take advantage of the mongoose .then() method - see http://mongoosejs.com/docs/promises.html

Here you can do ..

EventModel.remove(args).then((removeResponse) => {
  return EventModel.findOne(args);
}).then((findResponse) => {
  // etc
})

These requests will happen synchronously.

Dorian answered 30/3, 2017 at 4:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.