Получение данных из MongoDB вызывает ошибку «Невозможно прочитать свойство 'firstname' of null '»
Я пытался вернуть некоторую информацию о пользователях и отобразить их через HTML. Но я получаю сообщение об ошибке: «Невозможно прочитать свойство 'firstname' of null" error ». Для хранения данных я использую MongoDB, для серверной службы Express и Node.js, а также для внешнего интерфейса Angular. Для связи между задней частью и внешним интерфейсом я делегировал это для HttpClient.Соединение с Mongo работает нормально, так как моя консоль получает все данные, но когда дело доходит до внешнего интерфейса, у меня возникает эта проблема.
Метод класса routes-index.js для подключения к MongoDB
router.get('/tasks', async (req, res) => {
let MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
res.json([
MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbo = db.db('angular-auth');
dbo.collection('users').find({}).toArray(function(err, result) {
if (err) throw err;
console.log(result);
//db.close;
});
})
])
});
Метод класса tasks.service.ts для возврата данных во внешний интерфейс
getTasks() {
return this.httpClient.get<any>(this.URL + '/tasks');
}
private-tasks.component.ts метод класса ngOnInit (), который предполагает получение и подписку данных
ngOnInit(): void {
this.tasksService.getTasks()
.subscribe(
res => {
console.log(res); //<===== this line is returning null value!
this.tasks = res;
},
err => console.log(err)
);
}
private-tasks.component.html класс
<ul class="list-group">
<li class="list-group-item" *ngFor='let task of tasks'>
{{task.firstname}}
</li>
</ul>
console.log (res); дает нулевое значение, но внутри оператора if / else оно на самом деле не равно нулю ... Насколько я уверен, что это не так ... потому что тот же метод дает мне вывод в консоли. Я тоже пробовал добавить? к {{task? .firstname}} таким образом я не получаю никаких ошибок, но все равно console.log (res); дает нулевое значение.
Вы можете что-нибудь подсказать, как подойти к этой проблеме?
Ответы
Причина - res.json
вызов на серверной стороне. Внешняя сторона кода кажется хорошей. Аргументом вызова функции должен быть объект, который вы возвращаете с сервера клиенту, но то, что вы передаете ему вместо этого, если все, что возвращает MongoClient.connect, - что, вероятно, ничто (я никогда не использовал его так что я не могу быть уверен).
Место, где вы вызываете, console.log
находится внутри самой внутренней функции обратного вызова. В момент запуска этого фрагмента кода база данных ответила, и ответ готов к отправке клиенту. Но вы пытаетесь отправить данные клиенту до запуска этого обратного вызова.
Итак, правильный подход - разместить res.json
внутри самого внутреннего обратного вызова, который запускается, когда данные доступны.
MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbo = db.db('angular-auth');
dbo.collection('users').find({}).toArray(function(err, result) {
if (err) throw err;
console.log(result);
res.json(result); // <-- res.json goes inside, after data is available
});
});
Это похоже на проблему с асинхронным режимом, вот что вы можете попробовать в своем файле service.ts:
- Вам понадобится какая-то модель монго для хранения данных. Например:
private tasks:TaskModel[] = []
- В дополнение к модели вам понадобится тема, которую вам нужно будет импортировать из rxjs.
import {Subject} from 'rxjs';
а также
private taskUpdated = new Subject<taskModel>[](); //create a new subject of type taskModel that you will add to
- Последний бит, который нужно обновить в вашем файле service.ts, будет следующим:
getTasks(){
this.httpClient.get<any>(this.URL + '/tasks')
.subscribe((taskData)=> {
this.taskNotes = taskData;
this.taskUpdated.next([...this.taskNotes])//adding in taskNotes
})
getTasksUpdatedAsListener(){
return this.taskUpdated.asObservable();//observable that you will subscribe to in component.ts
}
- Затем в файле component.ts вы создадите другой объект подписки и измените свой код на этот:
//subscription that needs to be created
private sub:Subscription;
ngOnInit(): void {
this.tasksService.getTasks()//this needs to go first. It will get data in the service file
this.sub = this.taskService.getTasksUpdatedAsListener()
.subscribe((data TaskModel[])=> {
console.log(data);//you should see the data come in as json
})
}
Сообщите мне, как это происходит!