Получение данных из MongoDB вызывает ошибку «Невозможно прочитать свойство 'firstname' of null '»

Aug 20 2020

Я пытался вернуть некоторую информацию о пользователях и отобразить их через 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); дает нулевое значение.

Вы можете что-нибудь подсказать, как подойти к этой проблеме?

Ответы

1 LazarLjubenović Aug 21 2020 at 04:35

Причина - 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
  });
});
Jexon Aug 20 2020 at 02:28

Это похоже на проблему с асинхронным режимом, вот что вы можете попробовать в своем файле service.ts:

  1. Вам понадобится какая-то модель монго для хранения данных. Например:
 private tasks:TaskModel[] = []
  1. В дополнение к модели вам понадобится тема, которую вам нужно будет импортировать из rxjs.
import {Subject} from 'rxjs';

а также

private taskUpdated = new Subject<taskModel>[](); //create a new subject of type taskModel that you will add to
  1. Последний бит, который нужно обновить в вашем файле 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
}
  1. Затем в файле 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
        })


}

Сообщите мне, как это происходит!