Mengambil data dari MongoDB menyebabkan kesalahan "Tidak dapat membaca properti 'firstname' of null" "

Aug 20 2020

Saya telah mencoba mengembalikan beberapa info pengguna dan menampilkannya melalui HTML. Tetapi saya mendapatkan kesalahan: "Tidak dapat membaca properti 'firstname' dari null" error "Untuk menyimpan data saya menggunakan MongoDB, untuk layanan backend Express dan Node.js dan untuk frontend Angular. Untuk berkomunikasi antara back dan frontend saya mendelegasikan itu ke HttpClient. Koneksi dengan Mongo berfungsi dengan baik karena konsol saya menerima semua data tetapi ketika sampai pada sisi frontend itu memberi saya masalah ini.

routes-index.js class method untuk koneksi dengan 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;
         });
      })
   ])
 });

task.service.ts metode kelas untuk mengembalikan data ke frontend

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

private-task.component.ts class ngOnInit () metode yang menganggap untuk mendapatkan dan berlangganan data

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

private-task.component.html kelas

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

console.log (res); memberikan nilai null, tetapi dalam pernyataan if / else sebenarnya bukan null ... Bagaimana saya yakin itu tidak ... karena metode yang sama memberi saya output di konsol. Saya telah mencoba juga untuk menambahkan? ke {{task? .firstname}} dengan cara itu saya tidak mendapatkan error apapun tapi masih console.log (res); memberikan nilai nol.

Adakah yang bisa Anda sarankan untuk menangani masalah ini?

Jawaban

1 LazarLjubenović Aug 21 2020 at 04:35

Pelakunya adalah res.jsonpanggilan di sisi belakang. Sisi depan kode tampak bagus. Argumen pemanggilan fungsi seharusnya menjadi objek yang Anda kembalikan dari server ke klien, tetapi apa yang Anda berikan sebagai gantinya jika MongoClient.connect apa pun yang dikembalikan - yang mungkin bukan apa-apa (saya belum pernah menggunakannya jadi saya tidak bisa memastikan).

Tempat Anda menelepon console.logada di dalam fungsi panggilan balik terdalam. Saat kode ini berjalan, database telah merespons dan respons siap dikirim ke klien. Tapi Anda mencoba mengirim data ke klien sebelum callback ini dijalankan.

Jadi pendekatan yang benar adalah dengan menempatkan res.jsondi dalam callback paling dalam, yang berjalan saat data tersedia.

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

Ini terdengar seperti masalah Async, berikut ini yang dapat Anda coba di file service.ts Anda:

  1. Anda perlu memiliki semacam model mongo untuk menyimpan data. Sebagai contoh:
 private tasks:TaskModel[] = []
  1. Selain model, Anda pasti ingin memiliki subjek yang perlu Anda impor dari rxjs.
import {Subject} from 'rxjs';

dan

private taskUpdated = new Subject<taskModel>[](); //create a new subject of type taskModel that you will add to
  1. Bit terakhir untuk diperbarui dalam file service.ts Anda adalah ini:
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. Kemudian di file component.ts Anda, Anda akan membuat objek langganan lain dan mengubah kode Anda menjadi ini:
//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
        })


}

Beri tahu saya bagaimana kelanjutannya!