如何等待RxJS内部订阅方法

时间:2017-05-09 23:49:49

标签: angular typescript async-await rxjs

在RxJS主题的​​订阅回调中,我希望在await函数上async。下面是打字稿发布者抱怨说的代码示例:

  

错误:(131,21)TS2304:找不到名称'await'。

async ngOnInit() {
  this.subscriber = dateSubscription.subscribe((date: Date) => {
    let dbKey = await this._someService.saveToDatabase(someObject);
    // wait for db write to finish before evaluating the next code
    // ... some other code here
  });
}

通常我在尝试在非async函数内调用await时会看到这一点。我是否需要进行订阅回调async或者我是否会犯错?函数saveToDatabaseasync,并返回一个解析为写入的数据库主键的promise。

6 个答案:

答案 0 :(得分:22)

您可以直接将异步签名添加到subscribe

中的匿名函数调用中
 this.subscriber = dateSubscription.subscribe(async (date: Date) => {
    let dbKey = await this._someService.saveToDatabase(someObject);
    // wait for db write to finish before evaluating the next code
    // ... some other code here
  });

答案 1 :(得分:7)

您无需使用await,也无需将Promise转换为Observable

<小时/> 来自Ben Lesh的CF Tweet

enter image description here

这是一个模拟函数saveToDatabase的示例:
(以及正在使用的Plunkr:https://plnkr.co/edit/7SDLvRS2aTw9gYWdIznS?p=preview

const { Observable } = Rx;

const saveToDatabase = (date) =>
  new Promise(resolve =>
    setTimeout(() =>
      resolve(`${date} has been saved to the database`),
      1000));

const date$ = Observable.of(new Date()).delay(1000);

date$
  .do(x => console.log(`date received, trying to save it to database ...`))
  .switchMap(date => saveToDatabase(date))
  .do(console.log)
  .subscribe();

输出:
enter image description here

答案 2 :(得分:1)

这是我解决此问题的方法

const title = await new Promise<string>(resolve => 
  this.translate.get('MYBOOK-PAGE.PLEASE_REMOVE')
   .subscribe(translated => {
     resolve(translated)
   }));

在这里,我正在做的就是将“可观察的”更改为“承诺”

  

注意:这里唯一的问题是这是一次演出,即。如果你   订阅后,您将无法再次访问它。适合我,所以分享   在这里。

答案 3 :(得分:1)

也许对此问题已进行了更新。我也有类似的需要等待响应,而不是在Observable实现中使用await或setTimeout()方法,现在一种更干净的方法是在完成订阅之前使用RxJS内置的interval()方法

在服务中尝试以下方法:

import { interval } from 'rxjs';
...

// inside your method
const source = interval(100);
    source.subscribe(x => {
        subject.next(CONNECTIONS_DATA);
        subject.complete();
});
return subject;

RxJS文档: https://rxjs-dev.firebaseapp.com/guide/subject#reference-counting

如果有人最近尝试这样做,希望会有所帮助。

答案 4 :(得分:0)

您不能直接await可观察,但您可await Promise。您可以在observables订阅上使用.toPromise()方法。请考虑以下事项:

async ngOnInit() {
  const date = await dateSubscription.toPromise();      
  let dbKey = await this._someService.saveToDatabase(someObject);
}

await承诺dateSubscription时,您将获得Date个对象。然后,您可以继续执行下一行,这样可以更顺序地读取代码。

有些人认为角度不会等待ngOnInit完成,它没有选择权。查看给定JavaScript here的结果TypeScript。如您所见,ngOnInit将调用内部管理和执行底层状态机(生成器)的awaiter。 Angular对此没有任何控制权。它只是想要调用该方法。

答案 5 :(得分:-1)

async ngOnInit() { }是不正确的签名,因为这是Angular定义OnInit接口的方式。它应该返回void

 export interface OnInit { ngOnInit(): void; }

如果您承诺在dateSubscription之后处理,则可以使用Observable.fromPromise

 dateSubscription
 .flatMap(x=>
      Observable.defer(Observable.fromObservable(this._someService.saveToDatabase(someObject)))
   ).subscribe()