Mengambil data dari MongoDB menyebabkan kesalahan "Tidak dapat membaca properti 'firstname' of null" "
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
Pelakunya adalah res.json
panggilan 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.log
ada 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.json
di 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
});
});
Ini terdengar seperti masalah Async, berikut ini yang dapat Anda coba di file service.ts Anda:
- Anda perlu memiliki semacam model mongo untuk menyimpan data. Sebagai contoh:
private tasks:TaskModel[] = []
- 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
- 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
}
- 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!