如何使用先前http请求中的数据发出http请求?

时间:2017-07-06 22:20:24

标签: angular typescript rxjs ngrx-effects ngrx-store

我有一个Issue对象,其中一个属性是Tool对象的数组。问题和工具是我数据库中的两个不同的表。

在我的issues-log.component中,我正在调度一个操作来搜索与我的搜索查询匹配的问题。这很好用。

我接下来要做的就是获取问题列表,并针对每个问题ID,将其传递给我的工具服务,以便我可以获得与该问题相关的工具。

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

在我开始获取与每个问题ID相关联的工具之前,我宁愿不要等到我的API调用才能获得问题列表。是否可以在我的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([])));
});

我也试过从我的问题服务中调用我的工具服务,但不要认为这是正确的方法。

1 个答案:

答案 0 :(得分:1)

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

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

概念分解:

  1. 我们提出问题
  2. 我们将问题传递给另一个可观察的流,以便立即访问
  3. 我们使用这些问题进行其他异步调用
  4. 我们返回最终调用的结果,也可以订阅
  5. 因此,您必须使用此方法订阅两个可观察的流。

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

    @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
            });
        }
    }
    

    这对你有用吗?