La recuperación de datos de MongoDB provoca el error "No se puede leer la propiedad 'nombre' de nulo""

Aug 20 2020

He estado tratando de devolver la información de algunos usuarios y mostrarlos a través de HTML. Pero recibo el error: "No se puede leer la propiedad 'nombre' de nulo" error" Para almacenar datos, estoy usando MongoDB, para el servicio de backend Express y Node.js y para el frontend Angular. Para comunicarme entre backend y frontend delegué eso a HttpClient La conexión con Mongo funciona bien ya que mi consola recibe todos los datos, pero cuando se trata de la interfaz, me está dando este problema.

Método de clase route-index.js para conexión con 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;
         });
      })
   ])
 });

método de clase tasks.service.ts para devolver datos a la interfaz

getTasks() {
return this.httpClient.get<any>(this.URL + '/tasks');
}

private-tasks.component.ts class ngOnInit() método que supone obtener y suscribir datos

ngOnInit(): void {
this.tasksService.getTasks()
  .subscribe(
    res => {                             
      console.log(res);    //<===== this line is returning null value!
      this.tasks = res;                  
    },
    err => console.log(err)
  );
}

clase private-tasks.component.html

<ul class="list-group">
 <li class="list-group-item" *ngFor='let task of tasks'>
  {{task.firstname}}
 </li>
</ul>

consola.log(res); da un valor nulo, pero dentro de la declaración if/else en realidad no es nulo... Cómo estoy seguro de que no lo es... porque el mismo método me está dando salida en la consola. He intentado también agregar ? a {{task?.firstname}} de esa manera no obtengo ningún error, pero aún así console.log(res); da valor nulo.

¿Hay algo que pueda sugerir sobre cómo abordar este problema?

Respuestas

1 LazarLjubenović Aug 21 2020 at 04:35

El culpable es la res.jsonllamada en el lado de back-end. El lado frontal del código parece bueno. Se supone que el argumento de la llamada a la función es un objeto que devuelve del servidor al cliente, pero lo que le está dando en su lugar si MongoClient.connect devuelve lo que sea, que probablemente no sea nada (nunca lo he usado así que no puedo estar seguro).

El lugar al que llama console.logestá dentro de la función de devolución de llamada más interna. En el momento en que se ejecuta este fragmento de código, la base de datos ha respondido y la respuesta está lista para enviarse al cliente. Pero intenta enviar los datos al cliente antes de que se ejecute esta devolución de llamada.

Entonces, el enfoque correcto es colocar res.jsondentro de la devolución de llamada más interna, que se ejecuta cuando los datos están disponibles.

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

Esto suena como un problema de Async, esto es lo que puede probar en su archivo service.ts:

  1. Deberá tener algún tipo de modelo mongo para almacenar los datos. Por ejemplo:
 private tasks:TaskModel[] = []
  1. Además de un modelo, querrá tener un sujeto que deberá importar desde rxjs.
import {Subject} from 'rxjs';

y

private taskUpdated = new Subject<taskModel>[](); //create a new subject of type taskModel that you will add to
  1. El último bit para actualizar en su archivo service.ts sería este:
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. Luego, en su archivo component.ts, creará otro objeto de suscripción y cambiará su código a esto:
//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
        })


}

¡Déjame saber como va!