如何使用 switchMap 从 Wordpress REST API 中获取某个 post、其标签和评论,然后使用 JS 组合结果值?

How to get a certain post, its tags and comments from Wordpress REST API using switchMap and then combine the resulting values using JS?

我正在开发一个 Angular 应用程序,它需要从 Wordpress REST API 中获取具有给定 ID 的特定 post、其各自的标签名称和注释。此应用程序的工作方式与 Whosebug 的 question-answer-logic 非常相似,因此我将 Wordpress post 称为 question,将 Wordpress 评论称为 answers。使用 API 三个 GET 请求需要发送到服务器。第一个请求正在发送到 /wp/v2/posts/<id>。服务器的响应如下所示:

摘录post request

{
    "id": 9,
    "title": {
        "rendered": "Hello World! 3"
    },
    "tags": [
        2,
        3,
        4
    ]
}

tags 数组中的数字不是实际的 human-readable 标签名称,它们只是标签的标识符。在我们收到服务器的第一个响应后,我们需要向服务器发送另一个 GET 请求到 /wp/v2/tags?include=2,3,4,同时提供标签标识符。我们不需要数据库中可用的每个标签,只需要在对第一个请求的响应中引用的标签。换句话说,第二个请求取决于第一个请求的结果。来自服务器的第二个请求的响应如下所示:

摘录tags request

[
    {
        "id": 8,
        "name": "test"
    },
    {
        "id": 9,
        "name": "test2"
    },
    {
        "id": 30087,
        "name": "test3"
    }
]

第三个也是最后一个请求需要发送到 /wp/v2/comments?post=9。这会将结果集限制为分配给特定 post ID 的评论。服务器的响应如下所示:

comments request 的摘录:

[
   {
      "id":3,
      "post":4,
      "content":{
         "rendered":"<p>This is an example comment number 3.<\/p>\n"
      }
   },
   {
      "id":2,
      "post":9,
      "content":{
         "rendered":"<p>This is an example comment number 2.<\/p>\n"
      }
   }
]

Angular RxJS' switchMap 运算符似乎是要走的路。我的要求如下:

然后 .subscribe() 到整体流程并得到 post 的组合 object,然后可以在 Angular 模板中迭代其标签和评论.

编辑:在模板中,我需要显示 question/post 的标题、日期、内容和 human-readable 标签名称,以及 question/post 的内容和日期answer/comment.

到目前为止,我在 Stackblitz 中的代码看起来 like this。对我的代码的分叉将不胜感激。在编写解决方案时,我遇到了控制台错误:detail.component.ts 中第 44 行的 questions.map is not a function。我需要解决这个问题才能继续工作。

代码中用到的两个概念:

错误原因?

getQuestion() 服务中的方法处理对象而不是对象数组,如下所示。

/** GET specific post from the server based on given ID */
getQuestion(id: number): Observable<Question> {
    return this.http.get<Question>(`${this.questionsUrl}/posts/${id}`);
}

questions.map is not a functionmap RxJS operator 部分的 detail.component.ts 中抛出错误,因为我们正在尝试为一个对象调用 Array.map() 方法,这不会工作。

解决方案

可以通过创建临时数组并将 switchMap 参数变量 question 推入该临时数组来修复错误。之后,数组可以作为 of RxJS 运算符中的参数传递。所有这些都将在组件的getQuestion函数中完成,如下所示:

switchMap((question: Question) => {
    const tagIDs = question.tags.join(',');
    const questionID = +question.id;

    // create temporary empty array
    const tempArray = [];
    tempArray.push(question);

    return forkJoin({
        // reference the temporary array in the of operator call
        questions: of(tempArray),
        tags: this.questionService.getTags(tagIDs),
        comments: this.questionService.getDetailsAnswers(questionID),
    });
})

这有点粗糙,但有效并设法解决了问题。

最后可以在模板中显示数据,代码如下:

<div class="container m-5">
    <div *ngFor="let data of combined$ | async">
    <h1>{{ data.title.rendered }}</h1>
    <p>Asked {{ data.date | date: 'medium' }}</p>
    <hr />
    <p [innerHTML]="data.content.rendered"></p>
        <span *ngFor="let tag_name of data.tag_names">
    <a routerLink="/search/{{ tag_name }}/1" class="badge bg-secondary">{{
    tag_name }}</a>&nbsp; </span>
    <br /><br />
    <p>{{ data?.comments?.length }} answers</p>
    <div *ngFor="let answer of data.comments">
        <p [innerHTML]="answer?.content?.rendered"></p>
        <p class="text-end">Answered {{ answer?.date | date: 'medium' }}</p>
    <hr />
</div>

这里是 StackBlitz:https://stackblitz.com/edit/angular-ivy-puctmm?file=src%2Fapp%2Fdetail%2Fdetail.component.ts