Я создал простой веб-сайт с контрольным списком задач, где пользователи могут просматривать "Today's"
списки задач (на домашней странице), добавлять новые элементы в список, создавать и удалять другие списки задач. Весь мой код работал отлично. Поэтому я решил провести рефакторинг кода, чтобы отделить код Mon goose (MongoDB) в отдельный модуль с именем model.js
, из файла app.js
(где обрабатываются методы HTTP).
Теперь моя домашняя страница все еще загружается в браузере, однако Nodemon показывает, что приложение падает в терминале. Если я выберу какую-либо опцию на сайте, на странице просто ничего не отобразится. Поэтому, поскольку мое приложение падает по маршруту Home, я поместил операторы console.log
в app.get('/' ...
api и любые методы, которые оно вызывает из файла model.js
, чтобы попытаться отладить проблему, но безрезультатно. .
Прежде чем поделиться своим кодом, просто обратите внимание, что я поделился только кодом app.get('/' ...
и app.post('/'...
из файла app.js
, так как приложение падает на домашней странице и весь код из файла model.js
.
Вот мой код: 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'));
//*** HTTP requests' handlers
app.get('/', (req, res) => {
const defaultListName = "Today's";
const todayFormatted = date.getDate();
model.DBUtility.findOneList(defaultListName, (foundList) => {
console.log('inside model.DBUtility.findOneList');
if (!foundList) {
console.log('inside !foundList. Just before createNewListInDB');
model.DBUtility.createNewListInDB(defaultListName);
res.redirect('/');
} else {
res.render('list', {
listTitlePassToH1: foundList.name,
todayDate: todayFormatted,
listItems: foundList.items
});
console.log(`else render list. found list: ${foundList.name}`);
}
console.log('end of model.DBUtility.findOneList')
});
console.log(`end of app.get('/'`);
});
app.post('/', (req, res) => {
const receivedItem = req.body.newItem;
const listName = req.body.listName;
model.DBUtility.addNewItemToListInDB(listName, receivedItem);
if (listName === "Today's") {
res.redirect('/');
} else {
res.redirect('/' + listName);
}
});
const port = 3000;
app.listen(port, () => {
console.log(`Server started, listening on port: ${port}`);
});
модель. js:
const mongoose = require('mongoose');
//create DB
mongoose.connect('mongodb://localhost:27017/todolistDB', {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 {
constructor() {
console.log("Constructor class DBUtility");
}
// *** DB utility methods
static findOneList(listName, callBack) {
List.findOne({name: listName}, (err, foundList) => {
if (err) {
console.log(err);
} else {
console.log(`Found list: ${foundList.name}`);
var list = foundList;
}
callBack(list);
});
}
static findAllLists(callBack) {
List.find({}, (err, allLists) => {
if (err) {
console.log(err);
} else {
console.log(`Found all lists: ${allLists}`);
callBack(allLists);
}
});
}
static createNewListInDB(listName) {
//create default items for new list
const introItem = new Item({
name: 'Welcome to your todolist!'
});
const addItem = new Item({
name: 'Hit the + button to add a new item.'
});
const deleteItem = new Item({
name: '<-- Hit this to delete an item.'
});
const listNameCap = _.capitalize(listName);
const list = new List({
name: listNameCap,
items: [introItem, addItem, deleteItem]
});
list.save(err => {
if (err) return handleError(err);
console.log(`List ${list} added successfully to DB.`);
});
}
static addNewItemToListInDB(listName, itemName) {
console.log(`List passed: ${listName}`);
List.findOne({name: listName}, (err, foundList) => {
if (err) {
console.log(err);
} else {
foundList.items.push({ name: itemName });
foundList.save(err => {
if (err) return handleError(err);
console.log(`Item ${itemName} added to list ${listName} successfully.`);
});
}
});
}
static deleteItemFromListInDB(listName, itemID) {
// findOneAndUpdate is a mongoose method, but $pull is a mongoDB method
List.findOneAndUpdate({name: listName}, {$pull: {items: {_id: itemID}}}, (err, updatedList) => {
if (err) {
console.log(err);
} else {
console.log(`deleted item "${itemID}" from list ${updatedList} successfully.`);
console.log(`Updated list: ${updatedList}.`);
}
});
}
static deleteOneListFromDB(listID) {
List.findByIdAndDelete(listID, (err, deletedList) => {
if (err) {
console.log(err);
} else {
console.log(`Deleted list ${deletedList.name} successfully`);
}
});
}
}
exports.DBUtility = DBUtility;
Вот журналы и ошибка I получить в Терминале:
Server started, listening on port: 3000
end of app.get('/'
Found list: Today's
inside model.DBUtility.findOneList
else render list. found list: Today's
end of model.DBUtility.findOneList
events.js:288
throw er; // Unhandled 'error' event
^
TypeError: Cannot read property 'name' of null
Обратите внимание, у меня есть только один объект LIST, хранящийся в базе данных MongoDB, который является "сегодняшним" списком задач:
db.lists.find().pretty()
{
"_id" : ObjectId("5e98982a7f8b083a6cf2d433"),
"name" : "Today's",
"items" : [
{
"_id" : ObjectId("5e98982a7f8b083a6cf2d430"),
"name" : "Welcome to your todolist!"
},
{
"_id" : ObjectId("5e98982a7f8b083a6cf2d431"),
"name" : "Hit the + button to add a new item."
},
{
"_id" : ObjectId("5e98982a7f8b083a6cf2d432"),
"name" : "<-- Hit this to delete an item."
}
],
"__v" : 0
}
Когда я удалил этот объект из MongoDB терминал использует:
> db.lists.deleteOne( {name: "Today's"} )
{ "acknowledged" : true, "deletedCount" : 1 }
Теперь даже моя домашняя страница больше не загружается. Я получаю:
This site can’t be reached
И ошибка в терминале такая же, однако я вижу только самый последний оператор console.log в app.get('/'...
Server started, listening on port: 3000
end of app.get('/'
events.js:288
throw er; // Unhandled 'error' event
^
TypeError: Cannot read property 'name' of null
Также, Модель. js и приложение. js находятся на одном уровне каталога:
Извините за длинное сообщение, но я хотел чтобы быть уверенным, что я полон объяснений.
EDIT Вот полное сообщение об ошибке:
[nodemon] restarting due to changes...
[nodemon] restarting due to changes...
[nodemon] starting `node app.js`
Server started, listening on port: 3000
end of app.get('/'
events.js:288
throw er; // Unhandled 'error' event
^
TypeError: Cannot read property 'name' of null
at C:\Users\hazzaldo\Desktop\...\todolist-v2\model.js:36:54
at C:\Users\hazzaldo\Desktop\...\todolist-v2\node_modules\mongoose\lib\model.js:4849:16
at C:\Users\hazzaldo\Desktop\...\todolist-v2\node_modules\mongoose\lib\model.js:4849:16
at C:\Users\hazzaldo\Desktop\...\todolist-v2\node_modules\mongoose\lib\helpers\promiseOrCallback.js:24:16
at C:\Users\hazzaldo\Desktop\...\todolist-v2\node_modules\mongoose\lib\model.js:4872:21
at C:\Users\hazzaldo\Desktop\...\todolist-v2\node_modules\mongoose\lib\query.js:4379:11
at C:\Users\hazzaldo\Desktop\...\todolist-v2\node_modules\kareem\index.js:135:16
at processTicksAndRejections (internal/process/task_queues.js:79:11)
Emitted 'error' event on Function instance at:
at C:\Users\hazzaldo\Desktop\...\todolist-v2\node_modules\mongoose\lib\model.js:4851:13
at C:\Users\hazzaldo\Desktop\...\todolist-v2\node_modules\mongoose\lib\helpers\promiseOrCallback.js:24:16
[... lines matching original stack trace ...]
at processTicksAndRejections (internal/process/task_queues.js:79:11)
[nodemon] app crashed - waiting for file changes before starting...