如何在rxjs中执行链序列

ada*_*wak 38 javascript http rxjs typescript angular

我想要的是:

this._myService.doSomething().subscribe(result => {
  doSomething()
});
.then( () => dosthelse() )
.then( () => dosanotherthing() )
Run Code Online (Sandbox Code Playgroud)

所以我想链接.然后像承诺一样.我如何在Rxjs中做到这一点?

this._myService.getLoginScreen().subscribe( result => {
      window.location.href = MyService.LOGIN_URL;
      /// I would like to wait for the site to load and alert something from       the url, when I do it here it alerts the old one
    });
   .then (alert(anotherService.partOfTheUrl())


getLoginScreen() {
  return this.http.get(myService.LOGIN_URL)
.flatMap(result => this.changeBrowserUrl())
.subscribe( result => //i want to do sth when the page is loaded//);
}

changeBrowserUrl(): Observable<any> {
return Observable.create( observer => {
window.location.href = myService.LOGIN_URL;
observer.next();
});
}
Run Code Online (Sandbox Code Playgroud)

use*_*222 62

then可观察量的等价物将是flatMap.您可以在此处查看一些使用示例:

对于您的示例,您可以执行以下操作:

this._myService.doSomething()
  .flatMap(function(x){return functionReturningObservableOrPromise(x)})
  .flatMap(...ad infinitum)
  .subscribe(...final processing)
Run Code Online (Sandbox Code Playgroud)

注意你的函数返回的类型,对于链式observable,flatMap你需要返回一个promise或一个observable.

  • 我不知道我会说flatMap相当于那时候.flatMap实际上对数据执行操作.http://reactivex.io/documentation/operators/flatmap.html (7认同)
  • 如果我们不想要第n个可观察的结果,而是想要原始事件而不进行转换,该怎么办? (4认同)

aus*_*per 13

更新了 rxjs 解决方案

自从回答这个问题以来,Rxjs 已经发生了很大的变化。

  • flatMap就是现在mergeMap
    • 或者switchMap,它们大多是可以互换的,但了解它们之间的区别是有好处的
  • .do()就是现在tap()
  • 链接现在在.pipe(). 所有操作都应在该管道内完成
    • 如果需要,您可以链接管道(例如,一个变量映射用户数组。另一个变量采用第一个变量并第二次映射它)

在发出原始呼叫后执行某些操作

设想

  • 进行 HTTP 调用(例如身份验证检查)
  • 该呼叫完成后,导航到另一个页面
this._myService.getAuthenticated()
  .pipe(
    tap(result => this._myService.navigateToHome())
  )
  .subscribe()
Run Code Online (Sandbox Code Playgroud)

链接多个调用

设想

  • 进行 HTTP 调用(例如身份验证检查)
  • 拨打第二次电话以获取更多信息
  • 两个通话结束后导航
this._myService.getAuthenticated()
  .pipe(
    // The Authentication call returns an object with the User Id
    switchMap(user => this._myService.getUserInfo(user.id))
    // After the user has been loaded, navigate
    tap(user => this._myService.navigateToHome())
  )
  .subscribe()
Run Code Online (Sandbox Code Playgroud)

请注意上面的示例:我假设这些调用是 HTTP,在被调用一次后就会取消订阅。如果您使用实时可观察对象(例如用户流),请确保取消订阅或使用takeUntil/first运算符。


Thi*_*ier 11

如果dosthelsedosanotherthing返回原始值,则使用的运算符是map.如果它是可观察的,则运营商是flatMap(或等同的).

如果你想做一些必要的事情.我的意思是在异步处理链之外,您可以利用do运算符.

假设dosthelse返回一个observable和dosanotherthing一个raw对象,你的代码将是:

this._myService.doSomething()
  .do(result => {
    doSomething();
  })
  .flatMap( () => dosthelse() )
  .map( () => dosanotherthing() );
Run Code Online (Sandbox Code Playgroud)

请注意,如果返回subcribe方法的返回值,它将对应于订阅对象而不是可观察对象.订阅对象主要是为了能够取消observable并且不能参与异步处理链.

事实上,大多数情况下,您在链的末尾订阅.

所以我会这样重构你的代码:

this._myService.getLoginScreen().subscribe( result => {
  window.location.href = MyService.LOGIN_URL;
  /// I would like to wait for the site to load and alert something from       the url, when I do it here it alerts the old one
  alert(anotherService.partOfTheUrl()
});

getLoginScreen() {
  return this.http.get(myService.LOGIN_URL)
    .flatMap(result => this.changeBrowserUrl())
    .do( result => //i want to do sth when the page is loaded//);
}

changeBrowserUrl(): Observable<any> {
  return Observable.create( observer => {
    window.location.href = myService.LOGIN_URL;
    observer.next();
  });
}
Run Code Online (Sandbox Code Playgroud)