首页 > 解决方案 > MongoDB 文档已添加但未在网站上显示(无需刷新)

问题描述

我有一个简单的待办事项列表网站。因此,您可以创建一个待办事项列表,并从列表中添加和删除项目。意思是,有一个List集合和一个Item集合,其中 aList可以有很多Items内部(项目数组)。我已将 Mongoose (MongoDB) 代码拆分为一个单独的文件 ( model.js),我的app.js文件是处理所有 HTTP 请求的地方。导入的所有 Mongoose 方法app.js都运行良好。问题是当我添加一个Item到 aList时,通过按下+网站上的按钮,它应该在列表中显示新项目。

在此处输入图像描述

但是,在我按下+按钮后,该项目仍然没有显示在列表中。需要刷新网站才能显示。该项目确实已成功添加到数据库中,因为我可以通过控制台日志和检查数据库本身来确认这一点。

+按钮触发文件中的app.post('/'...方法app.js,以便将项目添加到列表中。

我的下一个方法是使用PromiseaddItemToListInDB方法(在model.js文件中),并且使用Async Await它可以确保在呈现网页之前将项目添加到数据库中。但是,我对这种方法还有另一个问题。我没有返回更新列表的值(带有新添加的项目),而是[Object Promise]. 无论如何,Promise Async Await仍然没有解决原来的问题。不确定Promise在这种情况下是否需要 a 。

请参考我下面的代码(ps为简洁起见,我只包含了文件中的app.get('/'...(主路由方法)和app.post('/'...(添加项目方法)app.js。以及添加项目方法来自model.js)。

另外,提前为所有控制台日志道歉,但我试图调试这个问题。我不想对 Async Await 的执行顺序感到困惑。

app.js

const express = require('express');
const bodyParser = require('body-parser');
const date = require(`${__dirname}\\date.js`);
const model = require(`${__dirname}\\model.js`);
const ejs = require('ejs');
const _ = require('lodash');

const app = express();

app.use(bodyParser.urlencoded({ extended: true }));
app.set('view engine', 'ejs');
app.use(express.static('public'));

app.get('/', (req, res) => {
  const defaultListName = "Today's";
  const todayFormatted = date.getDate();
  model.DBUtility.findOneList(defaultListName, (foundList) => {
    if (!foundList) {
      model.DBUtility.createNewListInDB(defaultListName);
      res.redirect('/');
    } else { 
      res.render('list', {
        listTitlePassToH1: foundList.name,
        todayDate: todayFormatted,
        listItems: foundList.items
      });
    }
  });
});

app.post('/', (req, res) => {
  const receivedItem = req.body.newItem;
  const listName = req.body.listName;
  console.log(`before model.DBUtility.addItemToListAndGetUpdatedList(listName, receivedItem)`);
  const updatedList = model.DBUtility.addItemToListAndGetUpdatedList(listName, receivedItem);
  console.log(`After model.DBUtility.addItemToListAndGetUpdatedList(listName, receivedItem)`);
  console.log(`updatedList: ${updatedList}`);
  if (listName === "Today's") {
    res.redirect('/');
  } else {
    res.redirect('/' + listName);
  } 
});

const port = 3000;
app.listen(port, () => {
  console.log(`Server started, listening on port: ${port}`);
});

model.js

const mongoose = require('mongoose');
const _ = require("lodash");

//connect to DB
mongoose.connect('mongodb+srv://<username>:<password>.mongodb.net/database', {useNewUrlParser: true, useUnifiedTopology: true, useFindAndModify: false });

//create schema
const itemsSchema = new mongoose.Schema ({
  name: String
});

const listSchema = new mongoose.Schema ({
  name: String,
  items: [itemsSchema]
});

const Item = mongoose.model('Item', itemsSchema);
const List = mongoose.model('List', listSchema);


class DBUtility {

    // *** DB utility methods

    static addItemToListInDB(listName, itemName) {
        return new Promise((resolve, reject) => {
            List.findOne({name: listName}, (err, foundList) => {
                if (err) {
                    console.log(err);
                    reject(err);
                } else {
                    foundList.items.push({ name: itemName });
                    foundList.save(err => {
                        if (err) {
                            console.log(err);
                        } else {
                            console.log(`Item ${itemName} added to list ${foundList.name} successfully.`);
                            resolve(foundList);
                        }
                    });
                }  
            });
        });
    }

    static async addItemToListAndGetUpdatedList(listName, itemName) {
        try {
            const updatedList = await DBUtility.addItemToListInDB(listName, itemName);
            console.log(`inside addItemToListAndGetUpdatedList. updatedList ${updatedList}`);
            return updatedList;
        } catch (err) {
            console.log(err);
        }  
    }
}

exports.DBUtility = DBUtility;

终端输出:

Server started, listening on port: 3000
before model.DBUtility.addItemToListAndGetUpdatedList(listName, receivedItem) 
After model.DBUtility.addItemToListAndGetUpdatedList(listName, receivedItem) 
updatedList: [object Promise]
Item Cheese added to list Shopping successfully. 
inside addItemToListAndGetUpdatedList. updatedList { 
  _id: 5e9cb7b45ceafe2440e09995,
  name: 'Shopping',
  items: [
    { _id: 5e9cb7c45ceafe2440e09999, name: 'Bread' },
    { _id: 5e9cb7cc5ceafe2440e0999a, name: 'Lemons' },
    { _id: 5e9cb7d25ceafe2440e0999b, name: 'Eggs' },
    { _id: 5e9cb7ea5ceafe2440e0999d, name: 'Butter' },
    { _id: 5e9cbd585ceafe2440e0999e, name: 'Cheese' }
  ],
  __v: 6
}

有一件事要提,我希望这不是红鲱鱼,当我在我的计算机上本地托管 MongoDB 时,我不记得有这个问题。但是当我迁移到 MongoDB Atlas 云托管时,问题似乎开始出现了。

标签: javascriptnode.jsmongodbmongodb-query

解决方案


为什么你有错误:

您遇到此错误是因为在 post 请求处理程序中,更新 List 集合(model.DBUtility.addItemToListAndGetUpdatedList())的 db 操作是异步的,即它直到将来某个较晚时间才完成,因此,重定向响应在更新到 List 之前发送收集完成。

修复:

要解决此问题,您需要确保仅在更新操作完成后才发送重定向响应。您可以使用async/await.
使 post 请求处理程序成为一个async函数和awaitdb 操作以更新列表

// Note the async keyword used before the request handler function
app.post('/', async (req, res) => {
  const receivedItem = req.body.newItem;
  const listName = req.body.listName;
  // The await keyword below ensures the update operation completes
  // before moving to the next statement
  const updatedList = await model.DBUtility.addItemToListAndGetUpdatedList(listName, receivedItem);
  if (listName === "Today's") {
    res.redirect('/');
  } else {
    res.redirect('/' + listName);
  } 
});

这样,重定向响应只会在 List 集合的更新完成后发送。

要注意的另一件事是 db update 操作可能会引发错误,因此您可能需要考虑将model.DBUtility.addItemToListAndGetUpdatedList()方法调用包装在 a 中try/catch并处理任何潜在的错误。


推荐阅读