Angular 2:将 Observable 转换为 Promise

Posted

技术标签:

【中文标题】Angular 2:将 Observable 转换为 Promise【英文标题】:Angular 2: Convert Observable to Promise 【发布时间】:2016-08-15 02:35:56 【问题描述】:

Q) 如何将以下 observable 转换为 Promise,以便我可以使用 .then(...) 调用它?

我想转换成promise的方法:

  this._APIService.getAssetTypes().subscribe(
    assettypes => 
        this._LocalStorageService.setAssetTypes(assettypes);
    ,
    err => 
        this._LogService.error(JSON.stringify(err))
    ,
    () => 
  ); 

它调用的服务方法:

  getAssetTypes() 
    var method = "assettype";
    var url = this.apiBaseUrl + method;

    return this._http.get(url, )
      .map(res => <AssetType[]>res.json())
      .map((assettypes) => 
        assettypes.forEach((assettypes) => 
          // do anything here you might need....
      );
      return assettypes;
    );      
    

谢谢!

【问题讨论】:

下面的大多数答案都有 toPromise() 运算符,在 RxJS 5.5+ 中已被弃用 【参考方案1】:

rxjs7

lastValueFrom(of('foo'));

https://indepth.dev/posts/1287/rxjs-heads-up-topromise-is-being-deprecated

rxjs6

https://github.com/ReactiveX/rxjs/issues/2868#issuecomment-360633707

不要管。默认情况下它在 Observable 对象上。

Observable.of('foo').toPromise(); // this

rxjs5

import 'rxjs/add/operator/toPromise';
import 'rxjs/add/operator/map';

...

this._APIService.getAssetTypes()
.map(assettypes => 
  this._LocalStorageService.setAssetTypes(assettypes);
)
.toPromise()
.catch(err => 
  this._LogService.error(JSON.stringify(err));
);

【讨论】:

获取此错误:[ts] 类型“(资产类型:任何)=> void”的参数不可分配给“PromiseConstructor”类型的参数。类型 '(assettypes: any) => void' 中缺少属性 'all'。 (参数)资产类型:任何 getAssetTypes() 返回什么? 接口类型AssetType的数组 @GünterZöchbauer 已将 import 'rxjs/operator/add/toPromise'; 更改为:import 'rxjs/add/operator/toPromise'; ? toPromise 已弃用。我们现在该怎么做?【参考方案2】:

observable 可以像这样转换为 promise:

let promise=observable.toPromise();

【讨论】:

如果我将其转换为承诺,我也可以捕获错误吗? 你可以用try catch甚至用户promise.catch()包围【参考方案3】:

你真的不需要这样做,只是做......

import 'rxjs/add/operator/first';


this.esQueryService.getDocuments$.first().subscribe(() => 
        event.enableButtonsCallback();
      ,
      (err: any) => console.error(err)
    );
    this.getDocuments(query, false);

first() 确保订阅块只被调用一次(之后就好像你从未订阅过一样),与 promise then() 完全相同

【讨论】:

正确,promise 仅在 observables 完成时才解决,使用 .first() 或 .take(1) 将确保在第一次发出后就是这种情况。 这里的问题是我们不能使用async/await 模式。 first().toPromise() 会给你承诺,然后你可以使用 async/await【参考方案4】:

在你的情况下,使 Observable 成为 Promise 的正确方法是遵循

getAssetTypesPromise() Observable<any> 
  return new Promise((resolve, reject) => 
      this.getAssetTypes().subscribe((response: any) => 
        resolve(response);
      , reject);
    );

【讨论】:

这个可以进一步简化为return new Promise((resolve, reject) =&gt; this.getAssetTypes().subscribe(resolve, reject));【参考方案5】:

编辑:

.toPromise() 现在在 RxJS 7 中已弃用(来源:https://rxjs.dev/deprecations/to-promise)

新答案:

作为已弃用的 toPromise() 方法的替代品,您应该使用 两个内置静态转换函数之一 firstValueFrom 或 最后一个值来自。

例子:

import  interval, lastValueFrom  from 'rxjs';
import  take  from 'rxjs/operators';
 
async function execute() 
  const source$ = interval(2000).pipe(take(10));
  const finalNumber = await lastValueFrom(source$);
  console.log(`The final number is $finalNumber`);

 
execute();
 
// Expected output:
// "The final number is 9"

旧答案:

很多 cmets 声称 toPromise 已弃用,但正如您所见 here 并非如此。

所以请使用toPromise (RxJs 6) 如前所述:

//return basic observable
const sample = val => Rx.Observable.of(val).delay(5000);
//convert basic observable to promise
const example = sample('First Example')
  .toPromise()
  //output: 'First Example'
  .then(result => 
    console.log('From Promise:', result);
  );

异步/等待示例:

//return basic observable
const sample = val => Rx.Observable.of(val).delay(5000);
//convert basic observable to promise
const example = await sample('First Example').toPromise()
// output: 'First Example'
console.log('From Promise:', result);

阅读更多here。


注意:否则您可以使用.pipe(take(1)).toPromise,但如上所述,使用上面的示例应该没有任何问题。

【讨论】:

它已被弃用,可能会在 v8 中删除。您的链接适用于 v6。【参考方案6】:

toPromise 在 RxJS 7 中是 deprecated。

用途:

    lastValueFrom

当我们对值流感兴趣时使用。像以前的toPromise一样工作

例子

public async getAssetTypes() 
  const assetTypes$ = this._APIService.getAssetTypes()
  this.assetTypes = await lastValueFrom(assetTypes$);

    firstValueFrom

当我们对值流不感兴趣而只对第一个值感兴趣然后从流中取消订阅时使用

public async getAssetTypes() 
  const assetTypes$ = this._APIService.getAssetTypes()
  this.assetTypes = await firstValueFrom(assetTypes$); // get first value and unsubscribe

【讨论】:

【参考方案7】:

你可以通过如下一行代码将 Observable 转换为 Promise:

let promisevar = observable.toPromise()

现在您可以在 promisevar 上使用 then 根据您的要求应用 then 条件。

promisevar.then('Your condition/Logic');

【讨论】:

以上是关于Angular 2:将 Observable 转换为 Promise的主要内容,如果未能解决你的问题,请参考以下文章

Angular Firebase将Observable转换为普通对象以在组件内使用数据

Angular 2 Firebase Observable 承诺不会返回任何东西

如何以角度将 JSON 对象数组转换为 Observable 数组

如何将空 JSON 数据推送到 Observable<any[]> angular 2 类型的数组字段

将 JSON 对象数组转换为 Observable<string[]>

Angular 6:将 Observable 响应传递给另一个 Observable