MongoDBからデータを取得すると、「nullのプロパティ 'firstname'を読み取れません」エラーが発生します。

Aug 20 2020

一部のユーザー情報を返し、HTMLで表示しようとしています。しかし、「nullのプロパティ 'firstname'を読み取れません」というエラーが発生します。データを保存するには、MongoDBを使用しており、バックエンドサービスExpressとNode.js、およびフロントエンドAngularに使用しています。私のコンソールはすべてのデータを受信するので、Mongoとの接続は正常に機能しますが、フロントエンド側になると、この問題が発生します。

ルート-MongoDBと接続するためのindex.jsクラスメソッド

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;
         });
      })
   ])
 });

データをフロントエンドに返すためのtasks.service.tsクラスメソッド

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

private-tasks.component.tsクラス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-tasks.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ではありません...そうではないと確信しています... coz同じメソッドがコンソールに出力を表示します。私も追加しようとしましたか?{{task?.firstname}}にこのようにすると、エラーは発生しませんが、console.log(res);が表示されます。null値を与えます。

この問題に取り組む方法を提案できるものはありますか?

回答

1 LazarLjubenović Aug 21 2020 at 04:35

犯人はres.jsonバックエンド側の呼び出しです。コードのフロントエンド側は良さそうです。関数呼び出しの引数は、サーバーからクライアントに返すオブジェクトであると想定されていますが、MongoClient.connectが返すものがあれば、代わりにそれを与えます-これはおそらく何もありません(私はそれを使用したことがありません)だから私にはわかりません)。

呼び出す場所console.logは、最も内側のコールバック関数内です。このコードが実行された時点で、データベースは応答し、応答をクライアントに送信する準備ができています。ただし、このコールバックが実行される前に、データをクライアント送信しようとします。

したがって、正しいアプローチは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);
    res.json(result); // <-- res.json goes inside, after data is available
  });
});
Jexon Aug 20 2020 at 02:28

これは非同期の問題のように聞こえます。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
        })


}

どうなるか教えてください!