do(tap)vs subscribe

mgr*_*nko 15 javascript rxjs angular

编辑:在RxJs 6之前,tap被称为do.更新的标题也反映了点击.

我想了解Observables 的使用.subscribe.do方法的最佳实践.

例如,如果我需要在从服务器加载初始数据后做一些工作

const init$: Observable<MyData> = this._dataService.getData();

init$
  .do((initialData: MyData) => {
    this.data = initialData; // at this step I am initializing the view
  })
  .switchMap(() => loadExtraData)
  .subscribe((extraData) => {
     doSomething(extraData, this._data); // I need this._data here
  }); 
Run Code Online (Sandbox Code Playgroud)

我可以这样做 .subscribe

const init$: Observable<MyData> = this._dataService.getData()
  .shareReplay(1);

init$
  .subscribe((initialData: MyData) => {
    this.data = initialData; // at this step I am initializing the view
  })

init$
  .combineLatest(loadExtraData)
  .subscribe(([initialData, extraData]) => {
     doSomething(extraData, initialData); // I need this._data here
  }); 
Run Code Online (Sandbox Code Playgroud)

哪一个更好,为什么?

Vam*_*shi 19

编辑:对于RxJS 6或以上,读取do作为tap.

do用于副作用.subscribe用于调用可观察对象.更换dosubscribe创建不想要的结果.替换subscribedo甚至不会调用流.

考虑这些例子:

使用订阅:

const testObservable = Rx.Observable.create(function(observer){
   console.log('some heavy task, may be network call ');
   observer.next('success');
});

testObservable.subscribe(function(res){
    console.log('action 1');
});

testObservable.subscribe(function(res){
   console.log('action 2');
});
Run Code Online (Sandbox Code Playgroud)

上面代码的输出是

"some heavy task, may be network call "
"action 1"
"some heavy task, may be network call "
"action 2"
Run Code Online (Sandbox Code Playgroud)

你可以看到Rx.Observable.create被执行了两次.我们的目标只是做一次,但与行动2一起,也行动1.

使用do:

const testObservable = Rx.Observable.create(function(observer){
   console.log('some heavy task, may be network call ');
   observer.next('success');
});

testObservable
    .do(function(res){
        console.log('action 1');
    })  
    .subscribe(function(res){
        console.log('action 2');
    });
Run Code Online (Sandbox Code Playgroud)

输出将是

"some heavy task, may be network call "
"action 1"
"action 2"
Run Code Online (Sandbox Code Playgroud)

这就是我们真正想要的.我们需要'行动2'但在此之前也需要'行动1'.

为什么叫副作用:

因为与其他运营商不同,它不会影响流的流量.它接受响应,做某事,即使它修改了流将忽略它的响应.例如:

testObservable
    .do(function(res){
        console.log('action 1');
        return res+'some other text';
    })  
    .subscribe(function(res){
        console.log('action 1');
    });
Run Code Online (Sandbox Code Playgroud)

上面的代码仍将提供与以前相同的输出.所以无论你在do流中执行什么,都会忽略它并继续执行它.

如果我们正在进行纯粹的"功能反应式编程",我们不希望流中出现任何副作用.因此,do不鼓励并且主要仅用于调试目的.


mar*_*tin 3

subscribe()在您使用在运算符之间建立连接之前,Observable 链不会执行任何操作。所以你总是必须使用该subscribe()方法。

操作do()员的目的只是产生副作用。

根据我的经验,通常不可能完成所有操作subscribe(),有时您需要使用它do(),因为您的应用程序逻辑需要按特定顺序执行操作。

所以总的来说,我会尽量避免使用do()并将大部分逻辑放入subscribe(). 仅当我必须以不同的顺序执行操作时,我才会使用do().