การดึงข้อมูลจาก MongoDB ทำให้เกิดข้อผิดพลาด“ ไม่สามารถอ่านคุณสมบัติ 'ชื่อแรก' ของ null "
ฉันพยายามส่งคืนข้อมูลผู้ใช้บางส่วนและแสดงข้อมูลผ่าน HTML แต่ฉันได้รับข้อผิดพลาด: "Cannot read property 'firstname' of null" error "ในการจัดเก็บข้อมูลฉันใช้ MongoDB สำหรับบริการแบ็กเอนด์ Express และ Node.js และสำหรับส่วนหน้า Angular ในการสื่อสารระหว่างส่วนหลังและส่วนหน้าฉันมอบหมายให้ กับ HttpClient การเชื่อมต่อกับ Mongo ทำงานได้ดีเนื่องจากคอนโซลของฉันได้รับข้อมูลทั้งหมด แต่เมื่อมาถึงส่วนหน้ามันทำให้ฉันมีปัญหานี้
เมธอดคลาส route-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;
});
})
])
});
เมธอดคลาส task.service.ts สำหรับการส่งคืนข้อมูลไปยังส่วนหน้า
getTasks() {
return this.httpClient.get<any>(this.URL + '/tasks');
}
private-task.component.ts class 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-task.component.html คลาส
<ul class="list-group">
<li class="list-group-item" *ngFor='let task of tasks'>
{{task.firstname}}
</li>
</ul>
console.log (res); ให้ค่า null แต่ภายในคำสั่ง if / else จริง ๆ แล้วมันไม่ใช่ null ... ฉันแน่ใจได้อย่างไรว่าไม่ใช่ ... เพราะวิธีการเดียวกันคือให้เอาต์พุตในคอนโซล ฉันได้ลองเพิ่มด้วยหรือไม่? ถึง {{task? .firstname}} ด้วยวิธีนั้นฉันไม่ได้รับข้อผิดพลาดใด ๆ แต่ยังคงเป็น console.log (res); ให้ค่าว่าง
มีอะไรที่คุณสามารถแนะนำวิธีแก้ไขปัญหานี้ได้หรือไม่?
คำตอบ
ผู้ร้ายคือres.json
สายที่อยู่ด้านหลัง โค้ดส่วนหน้าดูเหมือนจะดี อาร์กิวเมนต์ของการเรียกใช้ฟังก์ชันควรเป็นวัตถุที่คุณส่งคืนจากเซิร์ฟเวอร์ไปยังไคลเอนต์ แต่สิ่งที่คุณให้แทนหากสิ่งใดก็ตามที่ MongoClient.connect ส่งกลับ - ซึ่งอาจไม่มีอะไรเลย (ฉันไม่เคยใช้ ดังนั้นฉันไม่แน่ใจ)
สถานที่ที่คุณโทรconsole.log
อยู่ภายในฟังก์ชันเรียกกลับด้านในสุด ในขณะที่โค้ดส่วนนี้ทำงานฐานข้อมูลได้ตอบสนองและพร้อมที่จะส่งคำตอบไปยังไคลเอนต์ แต่คุณพยายามส่งข้อมูลไปยังไคลเอนต์ก่อนที่จะเรียกใช้การเรียกกลับนี้
ดังนั้นแนวทางที่ถูกต้องคือการวางres.json
ไว้ใน callback ด้านในสุดซึ่งจะทำงานเมื่อข้อมูลพร้อมใช้งาน
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
});
});
สิ่งนี้ดูเหมือนจะเป็นปัญหา Async นี่คือสิ่งที่คุณสามารถลองได้ในไฟล์ service.ts ของคุณ:
- คุณจะต้องมีโมเดล mongo บางประเภทเพื่อเก็บข้อมูล ตัวอย่างเช่น:
private tasks:TaskModel[] = []
- นอกจากโมเดลแล้วคุณจะต้องมีหัวเรื่องที่คุณจะต้องนำเข้าจาก rxjs
import {Subject} from 'rxjs';
และ
private taskUpdated = new Subject<taskModel>[](); //create a new subject of type taskModel that you will add to
- บิตสุดท้ายที่จะอัปเดตในไฟล์ 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
}
- จากนั้นในไฟล์ 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
})
}
บอกให้ฉันรู้ว่ามันเป็นอย่างไร!