Angular订阅可观察对象的问题

25 浏览
0 Comments

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”上不存在。

有什么想法吗?

0
0 Comments

问题出现的原因是在返回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

0
0 Comments

问题:使用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的异步特性,确保在正确的时间点获取到需要的数据。

0
0 Comments

问题出现的原因是声明了一个类型为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
      );
    }
  );    
}

以上方法解决了问题,并且避免了可能出现的路由参数未传递导致的错误。

0