簡體   English   中英

angular 訂閱可觀察對象的問題

[英]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 並在需要提供的值時訂閱它。

請務必仔細閱讀文檔以了解可觀察對象的工作原理。

https://angular.io/guide/observables

由於 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM