[英]problem with angular subscribing an observable
我正在嘗試提供一項服務,從包含帖子數組的 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 /* the file path is set by components */){
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}}
我收到此錯誤: Errors while compiling. Reload prevented.
Errors while compiling. Reload prevented.
在 vscode typescript 中告訴我: Property 'title' does not exist on type 'object'
我嘗試了@msanford 的解決方案。 在查看后還有一件事要改變,但我真的不知道該怎么做: posts["posts"][id]
typescript 給我一個錯誤:
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'
有任何想法嗎?
您已聲明您的帖子類型為 object: _post:; object;
_post:; object;
而且,屬性“title”在類型“ object ”上不存在。
您應該使用帖子實際包含的字段聲明一個接口或 class 。 舉個例子:
interface Post {
id: number;
title: string;
body: string;
author: string;
// etc
}
並在您的類型聲明中使用它: _post: Post;
也就是說,正如其他人指出的那樣,您的服務和組件邏輯需要工作。
您通常不會在服務中使用 .subscribe() ,而是在服務的使用者(即組件)中使用。 所以,而不是
// Service
getPost(id: number) :object{
var post!: object;
this.getJsonFileservice.getJsonFile('assets/posts.json').subscribe((data :any)=>{
post = data["posts"][id];
});
return post;
}
使用簡單
// Service
getPost = (): Post => this.getJsonFileservice.getJsonFile<Post[]>('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
);
}
);
}
你也有一個競爭條件,你可以在路由器向你發送帶有 id 的參數之前請求一個帖子,這大概是你添加非空斷言運算符id:: number
的原因,因為編譯器告訴你它可能是null。這是有原因的,不要覆蓋它。
你有一個問題,你在分配之前返回帖子:
post = data["posts"][id];
最好的方法是返回一個 observable 並在需要提供的值時訂閱它。
請務必仔細閱讀文檔以了解可觀察對象的工作原理。
由於 Angular 使用的是 Typescript,因此您必須將 _post 標記為any
或使用您期望的字段為其創建一個 typescript 接口/類型。
哦,你也可以這樣做:
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._post = this.getPost.getPost(id);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.