[英]Using nested observables in Angular 4
I want to get all comments from comments.json using http and observable which I am doing right now successfully, now I just want to loop these "comments" within this observable such that for each actor id I can call another function and pass this id and fetch user detail. 我想使用http和observable从comments.json中获取所有评论,而我现在正在成功完成此操作,现在我只想在此observable中循环这些“评论”,以便对于每个actor id,我可以调用另一个函数并传递此id并获取用户详细信息。 Something similar done in This Question
在这个问题上做了类似的事情
I know getting user detail separately is not good idea but it is requirement. 我知道分别获取用户详细信息不是一个好主意,但这是必要条件。 I want to know do this by async pipe so that information keep updating.
我想知道通过异步管道执行此操作,以便信息不断更新。
I have a service below: 我在以下服务:
service.ts 服务
import { Injectable } from '@angular/core';
import {HttpClient} from '@angular/common/http'
import {IComment} from "../../comments";
import {Observable} from "rxjs/observable";
@Injectable()
export class CommentsDataService {
private _url:string = "../../../../assets/json/comments.json";
constructor(private http: HttpClient) { }
/**
* Return Sample json for
* Comment listing.
* @param Id
* @returns {json)
*/
getComments():Observable<IComment[]>
{
return this.http.get<IComment[]>(this._url)
}
/**
*
* @param commentObj
*/
saveComment(commentObj){
console.log(commentObj);
}
}
component 零件
ngOnInit() {
//Service call for Comments listing.
this.commentsDataService.getComments()
.subscribe(data=>this.commentsData = data)
}
HTML: HTML:
<div class="container">
<div class="row listCommentsContainer">
<div class="col-lg-8 col-sm-8" *ngFor="let commentData of commentsData; let i = index">
<ol style="list-style: none;">
<li class="listComments">
<div style="display: block">
<div style="display:inline-block;">
<a class="avatar">
<img style="" src="">
</a>
</div>
<a class="commentPostByUserName">
<span class="commentPostByUserName" style=""></span>
</a>
<div class="commentTime">{{commentData.time_stamp}}</div>
</div>
<div class="commentTextDisplay">{{commentData.object}}</div>
<br>
<!-- Click Reply -->
<div class="addReplyContainer" #commentData.id>
<a class="addReplyLink" (click)="showReplyTextArea($event, commentData.id)">Reply</a>
</div>
<!-- Add Reply -->
<div [attr.commentId]="commentData.id" class="addReplyContainer replyTextAreaContainer" style="display: none" >
<textarea (keyup)="keyUpCommentTextarea($event, reply, commentData.id)" (keyup.enter)="addReply($event, commentData.root_id)" [(ngModel)]="reply" style="width:100%"
class="replyText commentText addReplyTextarea form-control"></textarea>
<button [attr.commentId]="commentData.id" disabled class="btn btn-success addCommentBtn" (click)="addReply($event, commentData.root_id)">Add</button>
</div>
<!-- ----------- -->
<!-- List Replies -->
<div class="replies col-lg-8 col-sm-8" *ngFor="let reply of commentData.comment">
<ol style="list-style: none;">
<li class="listComments listReplies">
<div style="display: block">
<div style="display:inline-block;">
<a class="avatar">
<img style="" src="">
</a>
</div>
<a class="commentPostByUserName">
<span class="commentPostByUserName" style=""></span>
</a>
</div>
<div class="commentTextDisplay replyTextDisplay">{{reply.object}}</div>
</li>
</ol>
</div>
<!-- --------------- -->
</li>
</ol>
</div>
</div>
<!-- Add Comment-->
<div class="row">
<div class="addCommentContainer col-lg-6 col-sm-12">
<textarea (keyup)="keyUpCommentTextarea($event, comment)"
[(ngModel)]="comment" class="commentText form-control"
placeholder="Add Comment">
</textarea>
<button (click)="addComment($event)" class="btn addCommentBtn btn-success">Add</button>
</div>
</div>
</div>
comments.json comments.json
[{ "id":"123",
"root_id":"234",
"target_id": "2",
"object":"Nice!",
"actor":"user:123",
"time_stamp": "2 mins ago",
"comment":[
{
"id": "124",
"root_id":"234",
"target_id":"3",
"object":"Well!!",
"actor":"user:123",
"time_stamp": "2 mins ago"
},
{
"id": "125",
"root_id":"234",
"target_id":"3",
"object":"Great!",
"actor":"user:125",
"time_stamp":""
}
]
},
{
"id":"126",
"root_id":"234",
"target_id": "2",
"object":"Super.",
"actor":"user:124",
"time_stamp": "2 mins ago",
"comment":[
{
"id": "234",
"root_id":"234",
"target_id":"",
"object":"Cool.",
"actor":"user:123"
},
{
"id": "236",
"root_id":"234",
"target_id":"3",
"object":"hiii.",
"actor":"user:123",
}
]
}, {
"id":"345",
"root_id":"234",
"target_id": "12",
"object":"Interesting.",
"actor":"user:124",
"time_stamp": "2 mins ago"
}, {
"id":"444",
"root_id":"234",
"target_id": "12",
"actor":"user:125",
"object":"Cool.",
"time_stamp": "2 mins ago"
},
{
"id":"567",
"root_id":"234",
"target_id": "12",
"object":"Last Comment..",
"actor":"user:125",
"time_stamp": "2 mins ago"
}
]
user.json user.json
[
{
"profile_image":"/../../assets/images/no-user.png",
"first_name" : "jack",
"id":"124"
},
{
"profile_image":"/../../assets/images/no-user.png",
"first_name" : "john",
"id":"125"
},
{
"profile_image":"/../../assets/images/no-user.png",
"first_name" : "simon",
"id":"123"
}
]
The switchMap operator is the classic solution to this idea of making more async calls based on the results of the first one, achieved like this: switchMap运算符是此思想的经典解决方案,该思想基于第一个结果进行更多异步调用,实现如下:
getUser(id) {
return this.http.get<User>('/user/ + id'); // don't know your actual user endpoint or interface but this is a sample
}
getCommentsWithUsers() {
return this.getComments().switchMap(comments => // first we use switchMap to execute a new set of observables
// map the comments into an array of requests for the user and combine with the forkJoin and map operator and object.assign
(comments.length)
? Observable.forkJoin(comments.map(comment => this.getUser(comment.actor).map(user => Object.assign(comment, {actor: user}))
: Observable.of([])); // empty check needed becuase forkJoin breaks with empty array
}
I'm not familiar enough with your data schema to say this will work perfectly, you may need some minor modifications, but this idea should work more or less. 我对您的数据架构还不够熟悉,无法说这将完美地工作,您可能需要进行一些细微的修改,但是这个想法或多或少都可以工作。
You can try something like this 您可以尝试这样的事情
this.http.get('/comments')
.map(res => res.json())
.finally(() => this.isLoading = false) // here load actors
.subscribe(
data => this.orders = data,
error => console.log(error)
);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.