Angular订阅可观察对象的问题
Angular订阅可观察对象的问题
我正在尝试创建一个服务,该服务从包含帖子数组的JSON文件中获取帖子。
我已经有一个使用HttpClient
返回JSON文件内容的服务。
目标是显示完整的帖子内容。
获取JSON文件的服务:
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Injectable({ providedIn: 'root' }) export class GetJsonFileService { constructor(private http: HttpClient) {} getJsonFile(jsonFile: string /* 文件路径由组件设置 */){ return this.http.get(jsonFile,{observe: 'body', responseType: 'json'}); } }
通过id获取帖子的服务:
import { Injectable } from '@angular/core'; import { GetJsonFileService } from './get-json-file.service'; @Injectable({ providedIn: 'root' }) export class GetPostService { constructor(private getJsonFileservice: GetJsonFileService) {} getPost(id: number) :object{ var post!: object; this.getJsonFileservice.getJsonFile('assets/posts.json').subscribe((data :any)=>{ post = data["posts"][id]; }); return post; } }
显示帖子的组件:
import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { GetPostService } from '../services/get-post.service'; @Component({ selector: 'app-post-view', templateUrl: './post-view.component.html', styleUrls: ['./post-view.component.scss'] }) export class PostViewComponent implements OnInit { _post!: object; id!: number; constructor(private route: ActivatedRoute, private getPost: GetPostService){} ngOnInit(){ var id!: number; this.route.params.subscribe(params=>{ id = params.id; }); this._post = this.getPost.getPost(id); } }
当我尝试在组件模板中显示一些内容时,例如:
{{_post.title}}
我收到以下错误:
编译时出现错误,已阻止重新加载。
而在vscode typescript中,它告诉我:
对象上不存在属性'title'
我尝试了@msanford的解决方法。
在post-view中还有一件事要改变,但我不太清楚如何做:
posts["posts"][id]
typescript给我一个错误:
元素隐式具有“any”类型,因为类型为““posts””的表达式无法用于类型“Object”进行索引。 属性“posts”在类型“Object”上不存在。
有什么想法吗?
问题出现的原因是在返回post之前,post尚未被赋值。解决方法是返回一个可观察对象,然后在需要获取值时订阅它。确保仔细阅读官方文档,了解可观察对象的工作原理。
在Angular中,订阅可观察对象是一种常见的操作,它允许我们在异步操作返回结果后进行相应的处理。然而,有时候我们可能会遇到在订阅之前就返回了值的情况,这就会导致问题。
例如,在下面的代码中,我们尝试在赋值post之前返回它:
post = data["posts"][id];
这样的代码逻辑是错误的,因为在这之前post并没有被赋值,所以返回的结果将是undefined。为了解决这个问题,我们可以返回一个可观察对象,并在需要获取值时进行订阅。
Angular中的可观察对象可以通过使用RxJS库来创建。我们可以使用Observable类来定义一个可观察对象,并使用of操作符来返回我们想要的值。然后,我们可以在需要的时候订阅这个可观察对象,以获取返回的值。
下面是一个解决问题的示例代码:
import { Observable, of } from 'rxjs'; getPost(): Observable{ return of(data["posts"][id]); } // 在需要获取post值的地方订阅可观察对象 getPost().subscribe(post => { console.log(post); });
通过这种方式,我们就可以在返回post之前进行订阅,确保在获取值时不会出现undefined的情况。同时,我们也需要仔细阅读官方文档,了解更多关于可观察对象的使用方法和注意事项。
更多关于可观察对象的信息,请参考官方文档:https://angular.io/guide/observables
问题:使用Angular订阅Observable时出现问题。
原因:route.params.subscribe()是异步的,所以不能保证在调用getPost()时已设置id。需要在params.subscribe()的oncomplete处理程序中调用getPost()来确保。
解决方法:
1. 在_post变量前添加类型标记,将其标记为any类型,或者为其创建一个带有预期字段的TypeScript接口/类型。
2. 在oncomplete处理程序中调用getPost()来确保在调用getPost()时已设置id。
具体代码如下:
export class PostViewComponent implements OnInit { _post!: { title: string }; id!: number; constructor(private route: ActivatedRoute, private getPost: GetPostService){} ngOnInit(){ var id!: number; this.route.params.subscribe(params=>{ id = params.id; }); this.route.params.subscribe({ complete: () => { this._post = this.getPost.getPost(id); } }); } }
以上是关于Angular订阅Observable出现问题的原因和解决方法的介绍。在订阅Observable时,需要注意Observable的异步特性,确保在正确的时间点获取到需要的数据。
问题出现的原因是声明了一个类型为object的属性_post,但是object类型没有title属性。
解决方法是声明一个包含post实际属性的接口或类,并在类型声明中使用它。同时,将订阅操作放在组件中进行,而不是在服务中进行。具体代码如下:
// 声明一个包含post属性的接口 interface Post { id: number; title: string; body: string; author: string; // 其他属性 } // 在服务中返回一个Observable对象 getPost = (): Observable=> this.getJsonFileservice.getJsonFile ('assets/posts.json') // 在组件中订阅获取post数据 ngOnInit() { let id: number; this.route.params.subscribe( params => id = params.id, error => console.error, complete => { this.getPost.getPost().subscribe( posts => this._post = posts["posts"][id], error => console.error ); } ); }
以上方法解决了问题,并且避免了可能出现的路由参数未传递导致的错误。