RXJS可观察对象中.pipe()和.subscribe()方法的区别

116

我最近注意到我可以在.pipe()中返回一个值,但是在.subscribe()中却不能。

这两种方法之间有什么区别?

例如,如果我有这个函数,让我们称之为“存款”,它应该返回账户余额,如果我这样做:

deposit(account, amount){
    return this.http.get('url')
    .subscribe(res => {
        return res;
    }
}

它返回一个可观察对象,如果我这样做:

deposit(account, amount){
    return this.http.get('url')
    .pipe(
        map(res => {
            return res;
        });
    );
}

它按预期返回账户余额。

那么为什么呢?

2个回答

109

pipe 方法用于链接可观察对象的操作符,而 subscribe 用于激活可观察对象并监听发出的值。

pipe 方法是为了让 webpack 可以从最终的 JavaScript 包中删除未使用的操作符而添加的。这使得构建更小的文件更容易。

例如,如果我有这个函数,我们称之为“deposit”,它应该返回账户余额,如果我这样做:

deposit(account, amount){
    return this.http.get('url')
    .subscribe(res => {
        return res;
    }
}

它返回一个可观察对象。

但它不会返回那个。它会返回当你调用Subscribe时创建的Subscription对象。

如果我这样做:

deposit(account, amount){
    return this.http.get('url')
    .pipe(
        map(res => {
            return res;
        });
    );
}

它并不返回账户余额。它返回一个使用 map 操作符的 Observable。在您的示例中,map 操作符不执行任何操作。


8
此回答现在不完整。似乎缺少屏幕截图或代码片段。 - Mark Bolster
4
我认为他指的是原帖中的代码片段,而不是在回答中重复它们。这也让我感到困惑。 - Shafiq Jetha
4
我编辑了答案,加入了提问者的代码片段以提高可读性,感谢@ShafiqJetha指出缺失之处。 - vincenthavinh
1
我认为这个答案真的需要解释一下,是否可以在.pipe()里面移动一个lambda函数到.subscribe()里面。 - iSpain17

4

一个重要的区别是,当您不执行subscribe请求时,将永远不会发送该请求,并且pipe也永远不会被执行。以下是一个演示差异的工作示例

订阅

const { interval, of } = rxjs;
const { delay, take } = rxjs.operators;

this.http = { get: (url)=> of(url).pipe(delay(1000), take(1)) } // request simulator

deposit = (account, amount) => {
    return this.http.get('url')
      .subscribe(res => {
          console.log('hello from subscriber');
          return res;
      })
}

let subscription = deposit('',''); // immediately send request
// you can cancel request by subscription.unsubscribe()

console.log('subscribed');
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.5/rxjs.umd.min.js" integrity="sha256-85uCh8dPb35sH3WK435rtYUKALbcvEQFC65eg+raeuc=" crossorigin="anonymous"></script>

管道

const { interval, of,  } = rxjs;
const { delay, take, map } = rxjs.operators;

this.http = { get: (url)=> of(url).pipe(delay(1000), take(1)) } // request simulator

deposit = (account, amount) => {
    return this.http.get('url')
        .pipe(
            map(res => {
                console.log('hello from pipe');
                return res;
            })
        );
}

const observable = deposit('',''); // this will return observable and do nothing


console.log('nothing happen');
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.5/rxjs.umd.min.js" integrity="sha256-85uCh8dPb35sH3WK435rtYUKALbcvEQFC65eg+raeuc=" crossorigin="anonymous"></script>

管道 + 订阅

const { interval, of,  } = rxjs;
const { delay, take, map } = rxjs.operators;

this.http = { get: (url)=> of(url).pipe(delay(1000), take(1)) } // request simulator

deposit = (account, amount) => {
    return this.http.get('url')
      .pipe(
          map(res => {
              console.log('hello from pipe');
              return res;
          })
      );
}

const observable = deposit('',''); // this will return observable and do nothing

const subscription = observable.subscribe(result => { // this will send request 
  console.log('hello from subscriber')
}); 

// subscription.unsubscribe() - this will cancel request
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.5/rxjs.umd.min.js" integrity="sha256-85uCh8dPb35sH3WK435rtYUKALbcvEQFC65eg+raeuc=" crossorigin="anonymous"></script>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接