La récupération des données de MongoDB provoque l'erreur "Impossible de lire la propriété 'prénom' de null""
J'ai essayé de renvoyer certaines informations sur les utilisateurs et de les afficher via HTML. Mais j'obtiens l'erreur: "Impossible de lire la propriété 'prénom' de null" erreur "Pour stocker des données, j'utilise MongoDB, pour le service backend Express et Node.js et pour le frontend Angular. Pour communiquer entre le back et le frontend, j'ai délégué cela à HttpClient.La connexion avec Mongo fonctionne bien puisque ma console reçoit toutes les données, mais en ce qui concerne le côté frontal, cela me pose ce problème.
méthode de classe routes-index.js pour la connexion avec 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éthode de classe tasks.service.ts pour renvoyer des données à l'interface
getTasks() {
return this.httpClient.get<any>(this.URL + '/tasks');
}
méthode ngOnInit() de la classe private-tasks.component.ts qui suppose d'obtenir et de souscrire des données
ngOnInit(): void {
this.tasksService.getTasks()
.subscribe(
res => {
console.log(res); //<===== this line is returning null value!
this.tasks = res;
},
err => console.log(err)
);
}
classe 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); donne une valeur nulle, mais dans l'instruction if/else, ce n'est en fait pas null... Comment je suis sûr que ce n'est pas le cas... car la même méthode me donne une sortie dans la console. J'ai aussi essayé d'ajouter ? à {{task?.firstname}} de cette façon, je ne reçois aucune erreur mais toujours console.log(res); donne une valeur nulle.
Y a-t-il quelque chose que vous pouvez suggérer pour aborder ce problème ?
Réponses
Le coupable est l' res.json
appel du côté back-end. Le côté frontal du code semble bon. L'argument de l'appel de fonction est censé être un objet que vous renvoyez du serveur au client, mais ce que vous lui donnez à la place si tout ce que MongoClient.connect renvoie - ce qui n'est probablement rien (je ne l'ai jamais utilisé donc je ne peux pas être sûr).
L'endroit où vous appelez console.log
se trouve à l'intérieur de la fonction de rappel la plus interne. Au moment où ce morceau de code s'exécute, la base de données a répondu et la réponse est prête à être envoyée au client. Mais vous tentez d'envoyer les données au client avant l'exécution de ce rappel.
L'approche correcte consiste donc à placer res.json
à l'intérieur du rappel le plus interne, qui s'exécute lorsque les données sont 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
});
});
Cela ressemble à un problème Async, voici ce que vous pouvez essayer dans votre fichier service.ts :
- Vous aurez besoin d'une sorte de modèle mongo pour contenir les données. Par exemple:
private tasks:TaskModel[] = []
- En plus d'un modèle, vous voudrez avoir un sujet que vous devrez importer de rxjs.
import {Subject} from 'rxjs';
et
private taskUpdated = new Subject<taskModel>[](); //create a new subject of type taskModel that you will add to
- Le dernier élément à mettre à jour dans votre fichier service.ts serait ceci :
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
}
- Ensuite, dans votre fichier component.ts, vous créerez un autre objet d'abonnement et modifierez votre code en ceci :
//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
})
}
Faites-moi savoir comment ça se passe!