未在 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.games
是 undefined
。
即使你在浏览器控制台中看到,你也会先看到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>
由于某种原因从 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.games
是 undefined
。
即使你在浏览器控制台中看到,你也会先看到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>