Экспорт методов Mon goose в Node.js (TypeError: Невозможно прочитать свойство 'name' из null) - PullRequest
0 голосов
/ 17 апреля 2020

Я создал простой веб-сайт с контрольным списком задач, где пользователи могут просматривать "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 находятся на одном уровне каталога:

enter image description here

Извините за длинное сообщение, но я хотел чтобы быть уверенным, что я полон объяснений.

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...

Ответы [ 2 ]

1 голос
/ 17 апреля 2020

Ошибка

TypeError: Cannot read property 'name' of null

возникает, когда вы пытаетесь получить доступ к свойству 'name' нулевого объекта.

Таким образом, единственные кандидаты, где появляется ошибка, следуют шаблону obj.name.

Теперь, когда я думаю об этом, другим случаем будет name деструктуризация свойства, но если он изначально поддерживается, это вызывает другую ошибку.

Также

console.log('inside !foundList. Just before createNewListInDB');
model.DBUtility.createNewListInDB(defaultListName);
res.redirect('/');

функция model.DBUtility.createNewListInDB(defaultListName); - это асинхронный и после этого вы звоните res.redirect('/'). Я не знаю, как Node Express обрабатывает эту функцию внутренне, но вы должны перенаправить после создания задач.

Как

model.DBUtility.createNewListInDB(defaultListName)
.then(_ => {
  res.redirect('/');
});

- Редактировать

list переменная не была объявлена ​​вне оператора if и могла вызвать исключение list is not defined

    static findOneList(listName, callBack) {
        var list = null;

        List.findOne({name: listName}, (err, foundList) => {
            if (err) {
                console.log(err);
            } else {
                console.log(`Found list: ${foundList.name}`);
                list = foundList; 
            } 
            callBack(list); 
        });
    }

Кроме того, const _ = require("lodash"); не было включено в model.js. В качестве метода lodash был использован метод: static createNewListInDB(listName). Линия: const listNameCap = _.capitalize(listName);

0 голосов
/ 17 апреля 2020

Вы получаете ошибку в строке № 36 модели. js

console.log(`Found list: ${foundList.name}`)

Вы можете обновить свой код как

static findOneList(listName, callBack) {

        List.findOne({name: listName}, (err, foundList) => {
            if (err || !foundList) {
                console.log(err);
            } else {
                console.log(`Found list: ${foundList.name}`);
                var list = foundList; 
            } 
            callBack(list); 
        });
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...