未在 Observable<> 订阅中分配实例变量?

Instance variable not assigned in Observable<> subscribe?

由于某种原因从 Obersavable 订阅时我的游戏数组没有被分配,即使我确定从服务器返回正确的数据(数组)。

这是我的game.service.ts:

import { Injectable } from '@angular/core';
import { Game } from '../models/game';
import { of, Observable } from 'rxjs';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { catchError, map, tap } from 'rxjs/operators';
import { NGXLogger } from 'ngx-logger';

@Injectable({
  providedIn: 'root'
})
export class GameService {
  private gamesUrl: string = 'api/games';

  constructor(private http: HttpClient, private logger: NGXLogger) { }

  getGames(): Observable<Game[]> {
    return this.http.get<Game[]>(this.gamesUrl);
  }

  getGame(id: number): Observable<Game> {
    const url: string = (`${this.gamesUrl}/${id}`);
    return this.http.get<Game>(url).pipe(tap(_ => this.logger.debug(`fetched game id=${id}`)), catchError(this.handleError<Game>(`getGame id=${id}`)));
  }

  log (operation: string) {
    console.log(operation);
  }

    /**
   * Handle Http operation that failed.
   * Let the app continue.
   * @param operation - name of the operation that failed
   * @param result - optional value to return as the observable result
   */
  private handleError<T> (operation = 'operation', result?: T) {
    return (error: any): Observable<T> => {

      console.error(error); // log to console instead
      this.logger.debug(`${operation} failed: ${error.message}`);
      return of(result as T);
    };
  }
}

这是我的 games.component.ts:

import { Component, OnInit } from '@angular/core';
import { Game } from '../../models/game';
import { GameService } from 'src/app/services/game.service';
import { Observable } from 'rxjs';

@Component({
  selector: 'app-games',
  templateUrl: './games.component.html',
  styleUrls: ['./games.component.css']
})
export class GamesComponent implements OnInit {
  games: Game[];

  constructor(private gameService: GameService) { 
  }

  ngOnInit() {
    this.getGames();
  }

  getGames(): void {
    this.gameService.getGames().subscribe(games => this.games = games);
    console.log(`games: ${this.games}`);
  }

  getGame(id: number): Observable<Game> {
    return this.gameService.getGame(id);
  }
}

如您所见,我正在 games.component.ts 中调用 getGames,其中 game.service.ts 正在返回响应(Observable)。

出于某种原因,subscribe(games => this.games = games) 不起作用,我得到了 games 实例变量的 'undefined'。 我肯定得到了正确的响应,因为 subscribe(games => console.log(games)) 没有显示 'undefined' 而是一个对象数组。

为什么我的实例变量没有被赋值?

编辑: 这是 console.log 中的输出,如果我订阅(游戏 => console.log(游戏))

编辑: 如果我执行以下操作,控制台日志是正确的。但是如果我在它之外引用 'games' 数组,我又会得到 undefined:

  getGames(): void {
    this.gameService.getGames().subscribe((games) => {
      this.games = games;
      console.log(`games: ${this.games}`);
    });
    console.log(`all games: ${this.games}`); //this is undefined
  }

编辑:已解决 - 谢谢 dileepkumar jami 解决方案是删除 $ 符号和 '| async' 在我的模板中:

<li *ngFor="let game of games$ | async">{{game.title}}</li>

<li *ngFor="let game of games">{{game.title}}</li>

试试这个

getGames(): void {
    this.gameService.getGames().subscribe(games => {
      this.games = games;
      console.log(`games: ${this.games}`);
    );   

}

您可以在订阅箭头函数中访问游戏数组,您正在尝试 console.log(games: ${this.games});在您的服务 returns 响应之前。

 this.gameService.getGames().subscribe((games) =>  {
   this.games = games;
   console.log(`games: ${this.games}`);
 });

分配游戏 属性 后,您可以在组件中的任何位置访问该值。仍然无法访问该值,那么您应该检查控制台是否有任何错误。

更新 Javascript 是异步的,它不会等待您的服务完成执行其他代码,在您的情况下 console.log()getGames 中首先执行,然后调用订阅。因此 this.games 值为 undefined

getGames(): void {
    this.gameService.getGames().subscribe((games) => {
      this.games = games;
      console.log(`games: ${this.games}`);
    });
    console.log(`all games: ${this.games}`); //this is undefined
  }
  1.    getGames(): void { 
  2.      this.gameService.getGames().subscribe((games) => {
  3.        this.games = games;
  4.        console.log(`games: ${this.games}`);
  5.      });
  6.      console.log(`all games: ${this.games}`); //this is undefined
  7. }

我给你的代码行编号了。

正如预期的那样,the line6 将 return undefined

来自 line 2 to line 5 的代码需要一些时间才能完成,因为它有一个 API 调用。

因为Javascript是异步的,不会等待代码(第2行到第5行)执行完。 它开始执行 line6。但是,到那时,this.gamesundefined

即使你在浏览器控制台中看到,你也会先看到line6的输出,然后你才能看到line4

您可以执行以下代码块来查看 javascript 是如何异步工作的

function myFunction() {
  console.log('Hello');
}

setTimeout(myFunction, 3000);
console.log('hi');
As you can see, even though console.log('hi'); was written after setTimeout(myFunction, 3000);, hi would be printed first and then hello.

<p> So, javascript did not wait for the setTimeout(myFunction, 3000); to be finished and it started to execute the next line
</p>

编辑:已解决 - 谢谢 dileepkumar jami 解决方案是删除 $ 符号和 '|我的模板中的异步':

<li *ngFor="let game of games$ | async">{{game.title}}</li>

<li *ngFor="let game of games">{{game.title}}</li>