【问题标题】:Capturing JSONAPI Included into Angular Observable捕获包含在 Angular Observable 中的 JSONAPI
【发布时间】:2020-11-03 14:55:01
【问题描述】:

我正在尝试学习如何使用 jsonapi 从 Drupal 8 获取内容到我的 Angular 7 应用程序中,从 Preston So 的 book,Decoupled Drupal in Practice 开始。它没有展示如何从关系中获取资源并包含在内。

jsonapi 规范提供了一个包含函数,我可以在其中从节点获取相关资源,而无需进行单独的调用。

使用http://localhost/jsonapi/node/article/MYUUID?include=field_image 会以这种通用格式呈现一个不错的 json 对象。

jsonapi
data
--attributes
--relationships
included

我正在尝试获取包含的部分,但我的 ArticleService 仅获取数据的内容,我也想获取包含的部分。

我的文章.ts

export class Article {
  attributes: object;
  relationships: object;
  included: object;
}

我的文章.service.ts

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { catchError, map, mergeMap } from 'rxjs/operators';
import { Article } from '../articles/article';
import { Image } from '../articles/image';

const httpOptions = {
  headers: new HttpHeaders({ 'Content-Type': 'application/json'})
}

@Injectable({
  providedIn: 'root'
})
export class ArticleService {
  private articlesUrl = 'http://localhost/jsonapi/node/article';

  constructor(private http: HttpClient) {}
  getArticle(id: string): Observable<Article>
  {
    if (id) {
      return this.http.get<Article>(this.articlesUrl + '/' + id + '?include=field_image', httpOptions)
        .pipe(
          map(res => res['data'])
         )
        .pipe(
          catchError(this.handleError([]))
    );
    } 
  }
 private handleError<T> (result?: T) {
    return (error: any): Observable<T> => {
      console.error(error);
      return of(result as T);
    }
  }
}

所以我的第一个映射函数是从正文中检索数据对象。我应该可以放大它。我尝试设置 map(res =&gt; res['body']),然后是 map(res =&gt; res['']),它不返回任何对象。阅读 rxjs/operators 我看到一些操作符,如 mergeMap、concatMap 失败,因为我不了解如何获取整个响应正文的内容。我的搜索结果似乎没什么帮助,因此我正在寻找有关如何获取整个响应正文的指针。

【问题讨论】:

  • 从组件订阅 getArticle() 服务。 Observable 在您订阅之前不会被调用。
  • 您没有在 Angular 应用程序中使用客户端 JSON:API 库而是尝试手动解析响应的任何原因?
  • 在我的搜索中,我发现了一些与 Angular 2 相关的内容。它们可能会有所帮助,但我已经学会了在调试和研究答案时不要增加复杂性。因此,我对可用工具的无知会有所帮助,而您的评论会有所帮助。 @jelhan
  • 我认为如果你将 JSON:API 与客户端库结合起来,它大部分是值得的。 JSON:API 有效负载模式的设计目的不是易于解析。特别是链接资源需要一些代码。我不建议一遍又一遍地重新实现该逻辑。更不用说客户端缓存、链接和通过关系导航、允许通过链接重新加载、更新和删除关系等高级功能。
  • 你会推荐哪个?还是为 Angular 2 编写的一个通常就足够了,等待调整?

标签: angular rxjs drupal-8 json-api


【解决方案1】:

article.service.ts

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { catchError, map, mergeMap } from 'rxjs/operators';
import { Article } from '../articles/article';
import { Image } from '../articles/image';

const httpOptions = {
  headers: new HttpHeaders({ 'Content-Type': 'application/json'})
}

@Injectable({
  providedIn: 'root'
})
export class ArticleService {
  private articlesUrl = 'http://localhost/jsonapi/node/article';

  constructor(private http: HttpClient) {}
  getArticle(id: string): Observable<Article>
  {
    if (id) {
      return this.http.get<Article>(this.articlesUrl + '/' + id + '?include=field_image', httpOptions);
    } 
  }
 private handleError<T> (result?: T) {
    return (error: any): Observable<T> => {
      console.error(error);
      return of(result as T);
    }
  }
}

component.ts

import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { ArticleService } from './article.service'; // import ArticleService service from article.service.ts file

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name = 'Angular';
  // inject ArticleService to the component
  constructor(private articleService : ArticleService ) {
    this.getArticle(); call getArticle function onInit
  }
  

  getArticle() {
   const id = 12;  // getting article id 12 details
   // subscribe to getArticle service method will call HTTP request and return response
   this.articleService.getArticle(id).subscribe((response)=> {
      // on successful request this block get called
      console.log('response body');
      console.log(response);
      console.log('response actual data');
      console.log(response.body);
    }, (error)=> {
      // on error this block get called like 404, 500 http status 
  })
  }
}

【讨论】:

  • 这是工作演示 stackblitz.com/edit/… 在控制台中检查数据。
  • 你好!虽然此代码 sn-p 可能是解决方案,但including an explanation 确实有助于提高您的帖子质量。请记住,您是在为将来的读者回答问题,而这些人可能不知道您提出代码建议的原因。
  • 工作演示的链接有所帮助。当我删除 Observable
    并删除向所有人开放的 .pipe(map(res => res['data', 'included']) 时,我的工作正常。如果您更新答案以反映对文章的这些更改。 service.ts 我很乐意接受。
猜你喜欢
  • 2020-07-02
  • 2019-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-22
  • 1970-01-01
  • 2013-11-25
相关资源
最近更新 更多