【问题标题】:I'm trying to use async/await to get a service, but the second service returns don't fill my variables我正在尝试使用 async/await 来获取服务,但第二个服务返回不填充我的变量
【发布时间】:2019-06-18 02:28:20
【问题描述】:

我有一项服务可以从服务器获取列表。但是在这个列表中我需要调用另一个服务来返回徽标 img,服务返回 ok,但我的列表仍然是空的。我做错了什么?

我尝试在这两个服务中使用 async/await 稍后我尝试使用单独的函数来获取徽标,但我的 html 没有改变。

 async getOpportunitiesByPage(_searchQueryAdvanced: any = 'active:true') {
    this.listaOportunidades = await this._opportunities
      .listaOportunidades(this.pageSize, this.currentPage, _searchQueryAdvanced)
      .toPromise()
      .then(result => {
        this.totalSize = result['totalElements'];
        return result['content'].map(async (opportunities: any) => {
          opportunities.logoDesktopUrl = await this.getBrand(opportunities['brandsUuid']);
          console.log(opportunities.logoDesktopUrl);
          return { opportunities };
        });
      });

    this.getTasks(this.totalSize);
  }

没有错误,只是我的 html 没有改变。 在我的 控制台.log(机会.logoDesktopUrl); 返回未定义

但最终返回填充。

信息: 角 7 服务器亚马逊 AWS。

【问题讨论】:

  • this.getBrand() 是否返回一个 Promise?
  • 不,一个简单的服务getBrand(brandsUuid) { this .brandService .getById(brandsUuid) .subscribe( res => { console.log(res.logoDesktopUrl); return res.logoDesktopUrl; }); }
  • await 只等待 Promise。我建议查看其他 Observable 函数来执行此操作,例如 forkJoin

标签: javascript angular


【解决方案1】:

await用于等待promise

如果您想在getOpportunitiesByPage 中等待,您应该从getBrand 返回promise

修改getBrand函数如下。

getBrand(brandsUuid): Observable<string> {
  this.brandService.getById(brandsUuid).pipe(map(res => { 
    console.log(res.logoDesktopUrl); return res.logoDesktopUrl;
  }))
}

opportunities.logoDesktopUrl = await this.getBrand(opportunities['brandsUuid']); 更改为opportunities.logoDesktopUrl = await this.getBrand(opportunities['brandsUuid']).toPromise();

请确保您从rxjs/operators 导入了map

【讨论】:

    【解决方案2】:

    首先,当你await时,你不应该使用then

    其次,async/await 仅使用 Promises 运行。

    async getOpportunitiesByPage(_searchQueryAdvanced: any = 'active:true') {
      const result = await this._opportunities
        .listaOportunidades(this.pageSize, this.currentPage, _searchQueryAdvanced)
        .toPromise();
      this.totalSize = result['totalElements'];
      this.listaOportunidades = result['content'].map(async (opportunities: any) => {
        opportunities.logoDesktopUrl = await this.getBrand(opportunities['brandsUuid']);
        console.log(opportunities.logoDesktopUrl);
        return opportunities;
      });
    
      this.getTasks(this.totalSize);
    }
    
    getBrand(brandsUuid) { 
      return new Promise((resolve, reject) => {
        this.brandService.getById(brandsUuid).subscribe(res => { 
          console.log(res.logoDesktopUrl);
          return resolve(res.logoDesktopUrl);
        }, err => {
          return reject(err);
        });
      });
    }
    

    但是,因为 rxjs 是在 Angular 中使用的,所以你应该使用它而不是 async/await

    getOpportunitiesByPage: void(_searchQueryAdanced: any = 'active:true') {
      this._opportunities.listaOportunidades(this.pageSize, this.currentPage, _searchQueryAdvanced).pipe(
        tap(result => {
          // we do that here because the original result will be "lost" after the next 'flatMap' operation
          this.totalSize = result['totalElements'];
        }),
        // first, we create an array of observables then flatten it with flatMap
        flatMap(result => result['content'].map(opportunities => this.getBrand(opportunities['brandsUuid']).pipe(
            // merge logoDesktopUrl into opportunities object
            map(logoDesktopUrl => ({...opportunities, ...{logoDesktopUrl}}))
          )
        ),
        // then we make each observable of flattened array complete
        mergeAll(),
        // then we wait for each observable to complete and push each result in an array
        toArray()
      ).subscribe(
        opportunitiesWithLogoUrl => { 
          this.listaOportunidades = opportunitiesWithLogoUrl;
          this.getTasks(this.totalSize);
        }, err => console.log(err)
      );
    }
    
    getBrand(brandsUuid): Observable<string> {
      return this.brandService.getById(brandsUuid).pipe(
        map(res => res.logoDesktopUrl)
      );
    }
    

    这是stackblittz 上的一个工作示例

    可能有一种更简单的方法,但它可以运行:-)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-04-18
      • 2011-05-09
      • 1970-01-01
      • 2018-02-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多