mua*_*aaz 0 observable typescript angular
我正在尝试创建一个从包含帖子数组的 json 文件中获取帖子的服务。我已经有一个通过使用返回 json 文件内容的服务HttpClient。目标是显示完整的帖子内容。
获取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 /* the file path is set by components */){
return this.http.get(jsonFile,{observe: 'body', responseType: 'json'});
}
}
Run Code Online (Sandbox Code Playgroud)
通过 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;
}
}
Run Code Online (Sandbox Code Playgroud)
显示帖子的组件:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
当我尝试在组件模板中显示某些内容时,例如:
{{_post.title}}
我收到这个错误:
Errors while compiling. Reload prevented.
在 vscode 中打字稿告诉我这一点:
Property 'title' does not exist on type 'object'
我尝试了@msanford的解决方案。在后期查看中还有一件事需要更改,但我真的不知道该怎么做:
posts["posts"][id]
打字稿给了我一个错误:
Element implicitly has an 'any' type because expression of type '"posts"' can't be used to index type 'Object'.
Property 'posts' does not exist on type 'Object'
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?
您已声明您的帖子属于对象类型:_post!: object;并且,属性“标题”在“对象”类型上不存在。
您应该声明一个接口或类,其中包含帖子实际包含的字段。举个例子:
interface Post {
id: number;
title: string;
body: string;
author: string;
// etc
}
Run Code Online (Sandbox Code Playgroud)
并在类型声明中使用它:_post: Post;
也就是说,正如其他人指出的那样,您的服务和组件逻辑需要工作。
您通常不会在服务中使用 .subscribe() ,而是在服务的使用者(即组件)中使用 .subscribe() 。所以,而不是
// Service
getPost(id: number) :object{
var post!: object;
this.getJsonFileservice.getJsonFile('assets/posts.json').subscribe((data :any)=>{
post = data["posts"][id];
});
return post;
}
Run Code Online (Sandbox Code Playgroud)
使用简单
// Service
getPost = (): Post => this.getJsonFileservice.getJsonFile<Post[]>('assets/posts.json')
Run Code Online (Sandbox Code Playgroud)
(编辑:我已经通过添加到调用中以常规方式将您的服务返回上面<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
);
}
);
}
Run Code Online (Sandbox Code Playgroud)
您还遇到了一个竞争条件,您可以在路由器向您发送带有 id 的参数之前请求发布,这可能就是您添加非空断言运算符 id !: number的原因,因为编译器告诉您它可能为空。这是有原因的,不要忽视它。
| 归档时间: |
|
| 查看次数: |
686 次 |
| 最近记录: |