【问题标题】:How can I return an array inside a key of a json in a service in Angular?如何在 Angular 的服务中返回一个 json 键内的数组?
【发布时间】:2021-05-29 13:16:48
【问题描述】:

一直在关注angular大侠的教程,后来想把它应用到我的小测试项目中巩固一下。当我将它与内置的 http 服务器和一些模拟项目一起使用时,它可以工作,但现在我无法从另一个 Django REST API 检索我想要的项目。

我可以测试这是我的 API 并且有效:

curl -H 'Accept: application/json; indent=4' http://127.0.0.1:5000/inventory/items_viewset/ -L
{
    "count": 13,
    "next": "http://127.0.0.1:5000/inventory/items_viewset/?page=2",
    "previous": null,
    "results": [
        {
            "label": "00004",
            "name": "Test2",
            "notes": "222",
            "owner": "admin",
            "photo": null
        },
        {
            "label": "0000007",
            "name": "Test1",
            "notes": null,
            "photo": "http://127.0.0.1:5000/media/item_images/2021/02/19/IMG_20210207_134147.jpg"
        },
    ]
}

然后我有我的物品item.ts

export interface Item {
  label: string;
  name: string;
  notes: string;
}

我有一个显示这些项目的组件items.component.ts

    items: Item[];  

    constructor(private itemService: ItemService, private messageService: MessageService) { }
    // constructor() { }

    ngOnInit(): void {
        this.getItems();
    }

    
    getItems(): void {
        this.itemService.getItems()
            .subscribe(items => this.items = items);
    }

在这里我有我正在尝试进行更改的服务

import { Injectable } from '@angular/core';
import { Item } from './item';
import { ITEMS } from './mock-items';
import { Observable, of } from 'rxjs';
import { MessageService } from './message.service';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { catchError, tap, map } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class ItemService {

    constructor(  private http: HttpClient, private messageService: MessageService) { }
  
    private itemsUrl = 'http://127.0.0.1:5000/inventory/items_viewset';  // URL to web api
    
    httpOptions = {
        headers: new HttpHeaders({ 'Content-Type': 'application/json',  })
    };
  
    getItems(): Observable<Item[]> {
return this.http.get<Item[]>(this.itemsUrl).pipe(
            map(res => res ),
            tap(_ => this.log('fetched items')),
            catchError(this.handleError<Item[]>('getItems', []))
        );  
    }
    
    
    /**
    * Handle Http operation that failed.
    * Let the app continue.
    * @param operation - name of the operation that failed
    * @param result - optional value to return as the observable result
    */
    private handleError<T>(operation = 'operation', result?: T) {
        return (error: any): Observable<T> => {

            // TODO: send the error to remote logging infrastructure
            console.error(error); // log to console instead

            // TODO: better job of transforming error for user consumption
            this.log(`${operation} failed: ${error.message}`);
            console.error(`${operation} failed: ${error.message}`);

            // Let the app keep running by returning an empty result.
            return of(result as T);
        };
    }
    
      /** Log a HeroService message with the MessageService */
    private log(message: string) {
        this.messageService.add(`ItemService: ${message}`);
    }
}

这可能有点乱,因为我删除了不相关的东西,但自从我切换到真正的 API 以来,我一直在工作的唯一一点就是这个方法:

getItems(): Observable<Item[]> {
return this.http.get<Item[]>(this.itemsUrl).pipe(
            map(res => res ),
            tap(_ => this.log('fetched items')),
            catchError(this.handleError<Item[]>('getItems', []))
        );  
    }

我已经有超过一天的空闲时间尝试解决此问题,但我无法找到如何从 JSON 访问密钥 results 以将其映射到项目。我发现的大多数类似问题都使用了.json() 的函数,我认为我已经理解该函数在HttpClient 中不再使用。然后我还尝试了多种形式,例如res.results,但没有成功,我得到一个异常,该属性不存在。

查询正在运行,就像我将点击线更改为:

tap(_ => console.log(_)),

我得到一个错误的对象。

有人可以给我一些提示我做错了什么吗?我不知道在哪里可以搜索我无法从教程中使它工作,我认为https://angular.io/api/common/http/HttpClient 的文档也没有涵盖这一点,我认为它应该很简单,但我不知道如何我可以进一步调试吗?

【问题讨论】:

  • 你骗了 HttpClient。您提供给 http.get 的泛型类型不是您期望 API 返回的类型,这就是它告诉您没有 results 属性的原因。
  • 你可以定义一个额外的类型,例如type Envelope&lt;T&gt; = { count: number, next: string | null, previous: string | null, results: T[] } 并使用它,但编译器只有在有准确信息的情况下才能帮助您。
  • 谢谢@jonrsharpe。您能否举例说明如何将此概念应用于我的 getItems 函数?

标签: json angular typescript angular-httpclient


【解决方案1】:

我想我终于让它工作了,但如果我想在很多地方使用这个函数,我不知道这是否是正确的方法,因为我需要在组件中使用很多代码,但如果我在分页上工作,可能请求我也需要其他参数。

按照@jonrsharpe 的建议,我删除了Item 并将其更改为any,然后我可以对组件中的响应进行一些解析: 儿子为我服务,我有item.service.ts

    getAllItems(): Observable<any> {
        return this.http.get(this.itemsUrl).pipe(
            tap(_ => this.log('fetched items')),
            catchError(this.handleError<Item[]>('getItems', []))
        );  
    }

在我的组件中,我使用 JSON items.component.ts

    items: Item[];  
    next: string;
    previous: string;

    ngOnInit(): void {
        this.getItems();
    }

    getItems() {
        this.itemService.getAllItems().subscribe(
            res => {
                console.log(res);
                if (res.results) {
                    this.items = res.results;
                }
                if (res.next) {
                    // set the components next transactions here from the response
                    this.next = res.next;
                    console.log(this.next);
                }
                if (res.previous) {
                    // set the components previous transactions here from the response
                    this.previous = res.previous;
                }
            }, 
            error => {console.log(error)}
        );
      }

我不会将问题设置为已解决,因为我只是一个初学者,我不知道这是否是正确的方法。但至少它似乎适用于我的场景。

【讨论】:

  • 我不建议从 getItems 或 http.get 中完全删除泛型类型。重点是更改 http.get 的通用类型,以使其实际匹配您期望响应包含的内容。然后编译器可以帮助您从响应中提取正确的属性,以从 getItems 中返回 Item[] 的 observable。
  • 作为一般说明,您为什么有条件地将 next、previous 和 results 分配给组件属性?这可能会使您处于请求 1 的结果、请求 2 的下一个结果和请求 3 的上一个结果的状态。您应该处理它们可能在应用程序的其他地方未定义的事实。毕竟,如果第一个请求失败,无论如何你都会有这种状态。
  • @Jusmpty 正如我所写,我最近开始学习 Angular,所以我没有太多背景。但我的想法是用项目构建一个表格,然后使用下一个和上一个来创建表格的页面,而在其他组件中只显示最近的项目。但是我又是一个完整的初学者,也许我做错了。如果这不是正确的方法,我很想得到另一个答案。
猜你喜欢
  • 1970-01-01
  • 2017-08-27
  • 2016-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-24
相关资源
最近更新 更多