Home > Software engineering >  Asynchronous CRUD operations with express
Asynchronous CRUD operations with express

Time:04-23

I have a basic CRUD application using html forms, nodejs/express and mongodb. I have been learning about synchronous vs asynchronous code via callbacks, promises, and async/await and to my understanding for a crud application you would want the operations to be asynchronous so multiple users can do the operations at the same time. I am trying to implement aync/await with my express crud operations and am not sure if they are executing synchronously or asynchronously.

Here is my update function, which allows a user to type in the _id of the blog they want to change, then type in a new title and new body for the blog and submit it. In its current state, to my knowledge it is executing synchronously:

app.post('/update', (req, res) => {
    const oldValue = { _id: new mongodb.ObjectId(String(req.body.previousValue)) }
    const newValues = { $set: { blogTitle: req.body.newValue, blogBody: req.body.newValue2 } }
    db.collection("miscData").updateOne(oldValue, newValues, function (err, result) {
        if (err) throw err;
        console.log("1 document updated");
        res.redirect('/')
    });

})

The way in which I was going to change this to asynchronous was this way:

app.post('/update', async (req, res) => {
    const oldValue = { _id: new mongodb.ObjectId(String(req.body.previousValue)) }
    const newValues = { $set: { blogTitle: req.body.newValue, blogBody: req.body.newValue2 } }
    await db.collection("miscData").updateOne(oldValue, newValues, function (err, result) {
        if (err) throw err;
        console.log("1 document updated");
        res.redirect('/')
    });

})

Both blocks of code work, however I am not sure if the second block of code is doing what I am intending it to do, which is allow a user to update a blog without blocking the call stack, or if the second block of code would only make sense if I was running more functions after the await. Does this achieve the intended purpose, if not how could/should I do that?

CodePudding user response:

db.collection(...).updateOne is always asynchronous, so you need not worry that a long-running database operation might block your application. There are two ways how you can obtain the asynchronous result:

With a callback function

db.collection(...).updateOne(oldValues, newValues, function(err, result) {...});
console.log("This happens synchronously");

The callback function with the two parameters (err, result) will be called asynchronously, after the database operation has completed (and after the console.log). Either err contains a database error message or result contains the database result.

With promises

try {
  var result = await db.collection(...).updateOne(oldValues, newValues);
  // Do something with result
} catch(err) {
  // Do something with err
}
console.log("This happens asynchronously");

The updateOne function without a callback function as third parameter returns a promise that must be awaited. The statements that do something with result will be executed asynchronously, after the database operation has successfully completed. If a database error occurs, the statements in the catch block are executed instead. In either case (success or error), the console.log is only executed afterwards.

(If updateOne does not have a two-parameter version, you can write

var result = await util.promisify(db.collection(...).updateOne)(oldValues, newValues);

using util.promisify.)

Your second code snippet contains a mixture of both ways (third parameter plus await), which does not make sense.

  • Related