【问题标题】:Angular2 subscribe inside subscribeAngular2订阅里面订阅
【发布时间】:2017-06-29 17:12:18
【问题描述】:

在 Angular2 中,根据第一个 API 调用的结果实现第二个 API 调用的正确方法是什么?我的 Angular2 组件之一具有以下方法。我尝试在完成时在另一个订阅中进行订阅,而第二个订阅的响应始终是“未定义”。

根据 CozyAzure 的建议进行编辑。

export interface Result {
  host: string;
  resourceUri: string;
  groupId?: string;
  resource?: any;
}

private curateResults(searchTerm: string, searchResults: SearchResults): Result[] {
    const results: Result[] = [];
    if (searchResults.results !== undefined && searchResults.results.length > 0) {
      searchResults.results.forEach((result: any) => {
        const processedSearchResult: Result = {
          host: result.origin.toString(),
          resourceUri: result.url.toString()
        };
        processedSearchResult.resource = undefined;
        processedSearchResult.groupId = undefined;
        this.bopsHttpService.getResourceData(processedSearchResult.host, processedSearchResult.resourceUri)
          .flatMap((resource: any) => {
            processedSearchResult.groupId = this.getGroupIdFromResource(resource, 'groupId');
            if (processedSearchResult.groupId === undefined) {
              const uriParts = processedSearchResult.resourceUri.split('/');
              const predicate = uriParts[uriParts.length - 2];
              if (predicate === 'group') {
                processedSearchResult.groupId = uriParts[uriParts.length - 1];
                return Observable.empty();
              } else {
                return this.bopsHttpService.getGroupRelation(processedSearchResult.resourceUri.split('/').pop());
              }
            } else {
              return Observable.empty();
            }
          })
          .subscribe((relation: any) => {
            if (relation !== undefined) {
              processedSearchResult.groupId = relation.objectId;
              console.log('Fetched Group ID: ', processedSearchResult.groupId);
            }
          });
        results.push(processedSearchResult);
      });
    }
  return results;
}

我的http调用如下:

  public getGroupRelation(subjectId: string): Observable<Relation> {
    const path = `${this.bopsServiceUrl}/relation/${subjectId}/group`;
    const queryParameters = new URLSearchParams();
    queryParameters.set('at', new Date().toISOString());
    const options = new RequestOptions({
      headers: this.headers,
      search: queryParameters
    });
    return this.http.get(path, options)
      .map((response: Response) => response.json())
      .catch((error: any) => Observable.throw(error.json().error
        || 'BOPS Server error during get group relation Operation', 
          error.json()));
  }

  public getResourceData(host: string, resourceUri: string): Observable<any> {
    const path = host + resourceUri;
    const queryParameters = new URLSearchParams();
    queryParameters.set('at', new Date().toISOString());
    const options = new RequestOptions({
      headers: this.headers,
      search: queryParameters
    });
    return this.http.get(path, options)
      .map((response: Response) => response.json())
      .catch((error: any) => Observable.throw(error
        || 'BOPS Server error during Get Resource Data Operation'));
  }

【问题讨论】:

  • 澄清一下,“processedSearchResult.groupId”始终未定义。

标签: angular angular2-services


【解决方案1】:

如果你想链接你的Observables,你需要使用.flatMap()flatMap().then() 相同,如果您考虑的是 Promise 方式。

改为这样做:

this.bopsHttpService.getResourceData(processedSearchResult.host, processedSearchResult.resourceUri)
    .flatMap(() => {
        //check if groupId exist, or whatever your logic is
        if(hasGroupId){
            //groupId exist, proceed to call your second request
            return this.bopsHttpService.getGroupRelation(processedSearchResult.resourceUri.split('/').pop());
        }
        //groupId doesn't exist, return an empty Observable.
        return Observable.empty();

    })
    .subscribe((relation) => {
        if (relation !== undefined) {
            processedSearchResult.groupId = relation.objectId;
            console.log('Fetched Group ID: ', processedSearchResult.groupId);
        }
    })

编辑:

您可以在 flatMap() 回调中进行任何干预。您可以检查groupId 是否存在,然后您才能继续进行下一个呼叫。如果没有,只需使用 Obersvable.empty() 返回一个空的 Observable。

【讨论】:

  • 感谢@CozyAzure 的建议。不知道我是否遵循这个。仅当来自第一个 API 调用的资源没有 groupId 时,我才必须进行第二个 api 调用。
  • 不幸的是,这不起作用。 processesSearchResult.groupId 仍未定义。
  • 由于我喜欢 flatMap 方法,我已经更新了我的代码,并根据您的建议更新了我的问题中的代码。看起来,在进行第二次 API 调用时,尽管结果成功,但 UI 并未等待订阅内的 groupId。
  • @Rama 如果 UI 没有更新,可能你需要一个 async 管道。 angular.io/api/common/AsyncPipe#!#examples
  • 我不必使用异步管道。我的 http 调用中有一个错误,一旦我修复它,我就可以让一切恢复正常。感谢您的帮助。
猜你喜欢
  • 2017-10-28
  • 2017-10-27
  • 2016-11-17
  • 2017-07-14
  • 1970-01-01
  • 1970-01-01
  • 2018-11-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多