如何使用先前的http请求中的数据创建http请求?

问题描述:

我有一个问题对象,其中一个属性是一个工具对象的数组。问题和工具是我数据库中的两个不同的表格。如何使用先前的http请求中的数据创建http请求?

在我的问题-log.component我调度一个动作来搜索匹配我的搜索查询的问题。这工作得很好。

我一直在试图做的下一件事是,将问题列表和每个问题ID都传递给我的工具服务,以便我可以获得与该问题相关的工具。

我能够得到这个工作的方式是添加另一个侦听ISSUE.SEARCH.COMPLETE操作的效果。然后,我浏览了我的工具服务中的一系列问题,以便我可以为每个问题ID调用API服务,并将工具属性添加到该问题。这在一些方面似乎是错误的。一个是,对于大型问题列表,需要很长时间才能加载所有工具,如果我尝试启动另一个问题搜索,我必须等待工具从前一个加载,然后我的应用才会响应。二,将整个问题数组传递到工具服务似乎是错误的,因为我一次只需要一个问题id来获取与该问题相关的工具列表;这不会使我的工具服务在我的应用程序的其他地方轻松重新使用。

我希望不要等到我的API调用才能获取问题列表,然后才能开始获取与每个问题ID相关的工具。是否可以在我的issuesSearch $ effect中添加代码,在下面评论的地方,开始添加工具,因为我的问题列表正在构建中?

组件:

@Component({ 
selector: issue-log, 
template: ` 
    <issue-search (search)="search($event)></issue-search> 
    <issue-list [issues]=$issues | async></issue-list> 
`, 
changeDetection: ChangeDetectionStrategy.OnPush 
}) 
export class IssueLogComponent { 
    issues$: Observable<Issue[]>; 

    constructor(private store: Store<fromRoot.State>) { 
    this.issues$ = store.select(fromRoot.getIssueSearchResults); 
    } 

    search(query) { 
    this.store.dispatch(new issue.IssueSearch(query)); 
    } 
} 

效果:

@Effect() issueSearch$: Observable<Action> = this.actions$ 
    .ofType(issue.ISSUE_SEARCH) 
    .debounceTime(300) 
    .map(toPayload) 
    .switchMap(query => { 
    if (query === '') { 
     return empty(); 
    } 
    const nextSearch$ = this.actions$.ofType(issue.ISSUE_SEARCH).skip(1); 
    return this.issueService.getIssuesFromQuery(query) //calls API service 
     .takeUntil(nextSearch$) 
     .mergeMap((res: Issue[]) => { 
     // How do I make another API call here, passing data from each element of res array? 
     return Observable.from([ 
      new issue.IssueSearchComplete(res) 
     ]) 
     }) 
     .catch(() => of(new issue.IssueSearchComplete([]))); 
}); 

我也试图从我的问题服务中打电话给我服务的工具,但不认为这是正确的做法无论是。

+0

我认为这[post](https://*.com/questions/35268482/chaining-rxjs-observables-from-http-data-in-angular2-with-typescript?rq=1)是有帮助的方向使用.flatMap或可能.forkJoin,但我仍然不确定将其包装在循环中以获取我的响应的每个元素。也许使用.forEach? – ksimonson10

+0

因此,您想要获得问题并能够立即访问这些问题,同时在每个问题中使用数据在后台进行更多异步调用? – Lansana

+0

是的,这可能吗? – ksimonson10

由于在使用这些问题的数据发出其他异步请求之前需要立即访问问题的结果,因此您可能需要使用某种RxJS Subject

您可以观察该主题的问题,并订阅所有最终调用结果的可观察值。

概念细分:

  1. 我们获取的问题
  2. 我们通过问题,另一个可观测流,使他们能够立即访问
  3. 我们使用的问题,使其他的异步调用
  4. 回到最终通话的结果,也可以订阅

所以你必须订阅用这种方法对两个可观察的流进行分析。

下面是一个简单的,人为的例子:

@Injectable() 
export class FooService { 
    issuesSubject: BehaviorSubject<Issue[]> = new BehaviorSubject([]); 

    get issues$(): Observable<Issue[]> { 
     return this.issuesSubject.asObservable(); 
    } 

    getIssuesAndMakeOtherAsyncCalls(): Observable<any> { 
     return this.issueService 
        .getIssuesFromQuery(query) 
        .flatMap((issues: Issue[]) => { 
         // This is where you add issues to the issues stream 
         this.issuesSubject.next(issues); 

         // This is where you make other HTTP calls using the issues 
         return this.makeSomeOtherCallsUsingIssues(issues); 
        }) 
    } 
} 

在您的组件:

@Component({}) 
export class FooComponent implements OnInit { 
    ngOnInit() { 
     this.issueService.getIssuesAndMakeOtherAsyncCalls().subscribe(res => { 
      // `res` will be the result of the `makeSomeOtherCallsUsingIssues(issues)` call in the service 
     }); 

     this.issueService.issues$.subscribe((issues: Issue[]) => { 
      // You will get issues here when the `this.issuesSubject.next(issues)` line is called in your service 
     }); 
    } 
} 

这是否对你的工作?

+0

谢谢你的回答!我正在尝试关注,但是您的方法名称中是否存在一些拼写错误?我有点麻烦。在组件中,this.issueService.getAllIssues()应该是'getIssuesAndMakeOtherAsyncCalls()'? – ksimonson10

+0

对不起,对,应该是!固定。 – Lansana

+0

再次感谢您的回答,但它没有解决对我来说最大的问题,那就是我实际上需要访问问题数组的每个元素中的属性,并将其传递到其他异步调用中。我认为问题出在我的数据结构中。我认为我需要将我的问题和工具存储为单独的列表,然后根据我的观点弄清楚如何合理地合并它们。 – ksimonson10