tap()内部的可观察对象完整

时间:2019-08-28 21:54:18

标签: javascript typescript rxjs

如果我在一个可观察对象上使用tap rxjs运算符调用另一个可观察对象,我可以保证它在管道的其余部分之前完成吗?

这里的想法是让服务对后端进行http调用,如果登录良好,则创建一个cookie,然后将映射后的响应返回给使用方组件。我要先确保已添加cookie,然后再继续确保没有任何竞争条件。

import { of, Observable } from 'rxjs';
import { map, tap } from 'rxjs/operators';


const httpObservable = loginAccount('fsdfds', 'fdsfsd');

httpObservable.subscribe(x => {
    console.log(x);
});



function loginAccount(username, password): Observable<any> {
    const httpResponse = of({ loggedIn: false, data: 'faketokenfrombackend' });

    return httpResponse.pipe(
        // Will this AWLAYS complete before map?
        tap(resp => fakeLocalStorage('Do something with the result')),
        // Will this AWLAYS complete before map?
        tap(resp => fakeLocalStorage('Do something else with the result')),
        map(resp => {
            if (!resp.loggedIn)
                return { success: false, message: 'really bad thing happened' };
            else
                return {success: true, message: 'WEEEEEE, it worked!'}
        }));
}

function fakeLocalStorage(data: string): Observable<boolean> {
    console.log('adding token to cookie');
    return of(true);
}

上面的脚本按预期将其输出到控制台窗口,但是我可以依靠它吗?

adding token to cookie
adding token to cookie
{success: false, message: "really bad thing happened"}

2 个答案:

答案 0 :(得分:1)

是的,RxJS将按顺序运行管道运算符。只要抽头运算符是同步的,它们就会在地图运算符运行之前完成。如果他们执行异步操作,则不会。

答案 1 :(得分:0)

tap仅执行提供的功能,然后发出输入值。 tap不会订阅Observable,因此当您执行tap(resp => fakeLocalStorage(..))时,fakeLocalStorage(..)返回的Observable不会被订阅。

如果您要在fakeLocalStorage(..)内预订Observable,那么显然这将是一个异步操作。 fakeLocalStorage(..)将立即返回并且tap将发出(最有可能在fakeLocalStorage(..)中订阅的Observable发出/完成)。

为确保在执行某些操作之前已完成其他可观察对象,您必须使用switchMap之类的映射函数将它们链接起来。

import { map, switchMap, mapTo, last, ignoreElements, endWith } from 'rxjs/operators';

httpResponse.pipe(
  // 'last()' just emits the last element which is mapped to the original response
  // if your inner Observable just emits one time you can remove 'last()'
  switchMap(resp => fakeLocalStorage('1').pipe(last(), mapTo(resp))),
  // you could also map to the Observable that should be executed
  // but ignore its output and append the input
  switchMap(resp => fakeLocalStorage('2').pipe(ignoreElements(), endWith(resp))),
  map(resp => {
    if (!resp.loggedIn)
      return { success: false, message: 'really bad thing happened' };
    else
      return { success: true, message: 'WEEEEEE, it worked!' }
  })
);
相关问题