1

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

在我的问题日志组件中,我正在调度一个操作来搜索与我的搜索查询匹配的问题。这工作得很好。

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

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

我不希望等到完成获取问题列表的 API 调用后,才能开始获取与每个问题 ID 关联的工具。是否可以在我的问题搜索 $ 效果中添加代码(在下面评论的地方),以便在构建我的问题列表时开始添加工具?

零件:

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

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

4

1 回答 1

1

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

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

概念分解:

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

那对你有用吗?

于 2017-07-10T14:16:27.637 回答