Home > Net >  Why server is sending back a response before changes are persisted in the database?
Why server is sending back a response before changes are persisted in the database?

Time:10-02

I am working on a task management application. I a have a controller for updating a board that receives a json from a client containing three properties: (1) title of a board, (2) list of column objects, each object has a name and id (optional) property, and (3) list of ids of columns that the user chose to delete.

The logic that I'm trying to execute here is the following: if there is a board title, that means title was changed and it should be updated. Then we iterate over the columns object. If the column object has an id with it, that means this column's name should be updated. If the object doesn't have an id with it, create a new column. In the end we iterate over the ids of deleted columns and find each column then delete.

 updateBoard: (req, res) => {
    /**If there is a new board title */
    if (req.body.title) {
      const updatedBoard = { title: req.body.title };
      Board.findByIdAndUpdate(req.params["id"], updatedBoard).exec();
    }

    req.body.columns.forEach((column) => {
      if (!column.columnId) {
        const newColumn = new Column({ title: column.columnName });
        newColumn.save();
        Board.findById(req.params["id"], (err, board) => {
          board.columns.push(newColumn);
          board.save();
        });
      } else {
        const updatedColumn = { title: column.columnName };
        Column.findByIdAndUpdate(column.columnId, updatedColumn);
      }
    });

    /**If there are columns to be deleted */
    if (req.body.deletedColumns) {
      req.body.deletedColumns.forEach((id) => {
        Column.findByIdAndDelete(id).exec();
      });
    }

    res.status(200).json({
      message: "done",
    });

  }

I don't know exactly how async javascript works here. It seems to be problem in the order of operations because the client fetches the new board after receiving a response but it doesn't get the new column in the board. I have to refetch again to see the updates.

Updated Code

This too doesn't work after adding async/await.

  updateBoard: async (req, res) => {
    /**If there is a new board title */
    if (req.body.title) {
      const updatedBoard = { title: req.body.title };
      await Board.findByIdAndUpdate(req.params["id"], updatedBoard).exec();
    }

    req.body.columns.forEach(async (column) => {
      if (!column.columnId) {
        const newColumn = new Column({ title: column.columnName });
        await newColumn.save();
        Board.findById(req.params["id"], async (err, board) => {
          board.columns.push(newColumn);
          await board.save();
        });
      } else {
        const updatedColumn = { title: column.columnName };
        await Column.findByIdAndUpdate(column.columnId, updatedColumn);
      }
    });

    /**If there are columns to be deleted */
    if (req.body.deletedColumns) {
      req.body.deletedColumns.forEach( async (id) => {
        await Column.findByIdAndDelete(id).exec();
      });
    }

    res.status(200).json({
      message: "done",
    });
  }

CodePudding user response:

req.body.columns.forEach(async (column) => {
  if (!column.columnId) {...}
})

does not wait for the asynchronous function to finish before moving on to the next column. Instead, write

for (var column of req.body.columns) {
  if (!column.columnId) {...}
}

and similar for req.body.deletedColumns.

  • Related