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?

duckegg
  • 1,379
  • 2
  • 13
  • 20
  • 4
    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. – SLaks Jul 02 '14 at 16:48
  • 1
    Check this link - http://stackoverflow.com/questions/17181248/making-mongoose-js-queries-run-synchronously/17296329#17296329 – Harpreet Singh Jul 02 '14 at 16:57
  • 1
    one more - http://stackoverflow.com/questions/24185367/mongoose-find-data-by-looping-on-an-array-of-models/24190334#24190334 – Harpreet Singh Jul 02 '14 at 16:59
  • I want to know, which link works for you (first or second)?. – Harpreet Singh Jul 06 '14 at 15:19
  • Your two posts provide the same idea, using `async.waterfall`. The latter link http://stackoverflow.com/questions/24185367/mongoose-find-data-by-looping-on-an-array-of-models/24190334#24190334 is much clearer. – duckegg Jul 06 '14 at 16:06
  • Possible duplicate of [Make a blocking call to a function in Node.js required in this case?](http://stackoverflow.com/questions/23879942/make-a-blocking-call-to-a-function-in-node-js-required-in-this-case) – Farid Nouri Neshat Dec 16 '16 at 05:40

1 Answers1

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.

danday74
  • 52,471
  • 49
  • 232
  • 283