การดึงข้อมูลจาก MongoDB ทำให้เกิดข้อผิดพลาด“ ไม่สามารถอ่านคุณสมบัติ 'ชื่อแรก' ของ null "

Aug 20 2020

ฉันพยายามส่งคืนข้อมูลผู้ใช้บางส่วนและแสดงข้อมูลผ่าน 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); ให้ค่าว่าง

มีอะไรที่คุณสามารถแนะนำวิธีแก้ไขปัญหานี้ได้หรือไม่?

คำตอบ

1 LazarLjubenović Aug 21 2020 at 04:35

ผู้ร้ายคือ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
  });
});
Jexon Aug 20 2020 at 02:28

สิ่งนี้ดูเหมือนจะเป็นปัญหา Async นี่คือสิ่งที่คุณสามารถลองได้ในไฟล์ service.ts ของคุณ:

  1. คุณจะต้องมีโมเดล mongo บางประเภทเพื่อเก็บข้อมูล ตัวอย่างเช่น:
 private tasks:TaskModel[] = []
  1. นอกจากโมเดลแล้วคุณจะต้องมีหัวเรื่องที่คุณจะต้องนำเข้าจาก rxjs
import {Subject} from 'rxjs';

และ

private taskUpdated = new Subject<taskModel>[](); //create a new subject of type taskModel that you will add to
  1. บิตสุดท้ายที่จะอัปเดตในไฟล์ 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
}
  1. จากนั้นในไฟล์ 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
        })


}

บอกให้ฉันรู้ว่ามันเป็นอย่างไร!