Observable和函数之间有什么区别

时间:2017-08-23 22:13:16

标签: angular rxjs observable

根据我的理解,Observable.create和普通的javascript函数看起来与我类似。那么两者之间的实际差异是什么?

var observable= Rx.Observable.create(function (observer) {
  observer.next("Hello World");
});
observable.subscribe(function (x) {
  console.log(x);
});

正常功能

function myfunction() {
  console.log('Hello World');

}

myfunction();

4 个答案:

答案 0 :(得分:3)

  

根据我的理解,Observable.create和普通的javascript函数看起来与我类似。那么两者之间的实际差异是什么?

它们都只是功能。 Observable看起来像黑魔法,但它归结为Javascript对象和函数。

基本上,首先我们需要一个observer。这只是一个具有三个属性的对象:

{
  //a function to be executed when we want the Observable to emit. Takes 1 arg
  next:     (val) : void

  //a func to be executed when an uncaught exception occurs. Takes 1 arg
  error:    (err) : void

  //a func to be executed when we want the Observable to stop. Takes no arg
  complete: () : void
}

现在考虑Observable.create

的签名
Observable.create(
  function(observer)
) : Observable {}

因此,要创建一个observable,我们将它传递给函数。此函数不会立即执行,但是当我们在.subscribe()返回的Observable上调用create()时,它将被执行。

要理解它,假设我们想要创建一个observable,每次更改时都会发出文本输入的新值。

let obs = Observable.create(observer=>{
  let input = document.querySelector('#myInput');
  input.onchange = (event) => {
     let newVal = event.target.value;
     if(newVal == 'stop') observer.complete();
     else observer.next(event.target.value);
   }
});

此时我们所拥有的只是一个对象obs,它存储了一个在我们调用subscribe时执行的函数。由于此函数需要一个尊重observer接口的参数,因此subscribe需要3个参数才有意义。当我们准备开始倾听价值变化时:

obs.subscribe(
  // this is the function that will be called from within the Observable
  // when the value changes. Behind the scenes this function is just
  // assigned to observer.next
  newVal => {console.log(newVal)},

  error => {}, // assigned to observer.error

  () => {}     // assigned to observer.complete. Executed if new val is 'stop'
)

现在您看到,每次在输入上引发onchange事件时,都会调用observer.next(newVal),这只是.subscribe()的第一个参数的另一个名称!

在我看来,Observable令人敬畏的是它们如何被链接或组合。也许我对了解所有价值变化并不感兴趣,只有那些长度大于3的人才感兴趣。我没有订阅原始obs,而是应用.filter()运算符:

obs.filter(newVal => newVal.length > 3).subscribe('...')

请注意,传递的是一个函数。最终结果是只有通过过滤器的输出才会达到.subscribe()。怎么做的?像这样:

class Observable {
  filter: (filterFunc) {
    // create a new observable. This is now what your code will subscribe to.
    // the original observable is now upstream, and accessed below
    return Observable.create( observer => {
      // subscribe to the original observable so we can see input value changes
      this.subscribe(
        // pass on the value only if it makes it through the filter
        newVal => {if(filterFunc(newVal)) observer.next(newVal)},
        // errors flow downstream
        error  => observer.error(error),
        // Stop immediately if the upstream observable completes
        complete => observer.complete()
      );
    } )
  }
}

再一次,没有什么神奇之处。 .filter()运算符创建了一个订阅原始observable的新observable。当原始发出时,new接收值并在将其自己的结果传递给其观察者之前以某种方式对其进行操作。因此,当您执行obs.filter(filterFunc).subscribe()时,您将收到第二个观察者的输出。数字和flexibility of these operators notify-me-when 设计范例配对使Observables如此强大。

我推荐RxJS 5的架构师this video。如果你只有几分钟,look at this post由同一架构师。

答案 1 :(得分:2)

最简单的思考方式是函数具有开始和结束。你叫它,它做了什么,然后结束。显然有例外,但为了这次谈话的目的,解释应该没问题。

另一方面,一个观察者最好被认为是一个"窗口"通过它可以查看数据流,以及有关如何在新数据显示时做出反应的说明"透过窗户。函数和observable之间的另一个区别是函数很可能是处理静态数据,而Observable正在处理流。因此,可观察到的时间成分是很多混乱发挥作用的地方。函数通常会捕获数据的快照并对其进行操作。观察者会随着时间的推移查看数据,并说明如何对其做出反应。

让我们以下面的例子来说明Observables在现代编程中是如此强大。假设我们有一个Users对象(静态数据)用于"函数方法"和UsersData可观察的(随时间推移的数据流),两者都为我们的应用程序中的用户传送数据。我们希望显示在我们的应用程序中注册的所有用户。

功能方法

function getUsers() {
    return Users;
}

getUsers();

此方法将在调用时返回所有用户。可能在页面加载并且模型被实例化时。页面加载后将其转换为静态数据。

可观察的方法

function getUsers() {
    UserDataObservable.subscribe(_Users => {
        this.Users = _Users
    }
}

getUsers();

subscribes观察点的可观察方法UserData允许我们将新数据推送到observable,后者又会更新模型的Users属性,从而更新视图。换句话说,它不仅最初抓取了数据的快照,而且还打开了一个数据窗口,以便观察新的数据并作出反应。

所以回到原来的问题,一旦你调用它就会完成你的功能,而你可以继续将字符串推送到你的observable并且它们会一直记录到控制台。

答案 2 :(得分:0)

可观察的是一个对象/实体,它对离散连续信息序列进行操作。离散信息集的示例是数组中的元素,对于连续信息,您可以考虑任何事件。订阅者是需要那些每次都被观察者隐式调用/给出的信息的人/函数。

  

以YouTube铃声为例。 YouTube会通知更新   您订阅并按下了铃铛图标的频道。无论您是否对该更新感兴趣。

但是函数是显式的,只有当你调用它时它才有效。

  

与您访问YouTube中的频道并观看视频一样。根据您的兴趣,您可以观看一些视频,但不是全部。

答案 3 :(得分:0)

我也从他们的官方文件中得到了一些很好的解释

Observable可以随时间“返回”多个值,而功能则不能。你不能这样做:

function foo() {
  console.log('Hello');
  return 42;
  return 100; // dead code. will never happen
}

函数只能返回一个值。但是,可观测量可以做到这一点:

var foo = Rx.Observable.create(function (observer) {
  console.log('Hello');
  observer.next(42);
  observer.next(100); // "return" another value
  observer.next(200); // "return" yet another
});

console.log('before');
foo.subscribe(function (x) {
  console.log(x);
});
console.log('after');

<强>结论:

  • func.call()表示“同步给我一个值
  • observable.subscribe()表示“给我任意数量的值 同步或异步