0

出于某种原因从 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 实例变量的“未定义”。我肯定会得到正确的响应,因为subscribe(games => console.log(games))没有显示“未定义”,而是显示了一个对象数组。

为什么没有分配我的实例变量?

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

在此处输入图像描述

编辑:如果我执行以下操作,控制台日志是正确的。但是,如果我引用它之外的“游戏”数组,我会再次未定义:

  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 解决方案是删除 $ 符号和 '| 我的模板中的异步':

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

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

3 回答 3

2
  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将返回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>
于 2019-02-20T05:40:38.890 回答
0

试试这个

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

}
于 2019-02-20T05:27:03.850 回答
0

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

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

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

UPDATE 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
  }
于 2019-02-20T05:33:28.633 回答