
RxJs本身就是一个庞大的话题,我们可以写一篇完整的文章。我已经看到并阅读了许多文章,其中有一些重要的、有限的主题和一些代码片段,但却找不到一篇这样的文章来完整地介绍它。所以,在这里我们要做一些不同的事情。
我们来看看:
=> RxJs这个词代表了Javascript的反应性扩展。它允许我们用异步数据流工作。它提供了一个核心类型。
即Observable,其他三种类型是Observer、Schedular和Subject。
RxJs中的Observables和Observers
因此,我们使用Observables来执行异步操作和处理异步数据。我们可以使用Promises或Observables在Angular中管理异步操作。现在,什么是异步操作和异步数据?我们已经知道,JavaScript是一种单线程的编程语言,这意味着代码是逐行执行的。
一旦一段代码完成,程序中的下一段代码才会被执行。所以,如果一个任务在执行中需要很长的时间,我们就会向服务器发出HTTP请求。在这种情况下,它将需要一些时间。所以,该HTTP请求后的下一条语句将不得不等待执行;只有当HTTP请求完成后,它才会得到执行。
因此,我们可以说,同步代码在本质上是阻塞的,这是因为异步编程进入了画面。异步代码在后台运行时不会停止主线程中的代码执行。所以,异步代码是非阻塞的。这意味着我们可以异步地进行HTTP请求。
在这种情况下,它将在后台运行,而该HTTP请求后的下一个代码将立即在主线程中得到执行。所以,在这种情况下,HTTP请求不会阻塞下一行的代码。使用一个异步程序,我们可以在不阻塞主线程的情况下执行长的网络请求。
我们可以通过两种方式做到这一点。
1.通过使用承诺
2.2.通过使用可观察变量
现在,Promises和Observables之间的区别是什么?
假设我们正在创建一个需要来自服务器的数据的应用程序,例如,从服务器上请求一个用户列表。在这种情况下,我们将从我们的应用程序向服务器发送一个请求。现在,服务器将从数据库或Web API中获取数据。
所以,我们所请求的数据是巨大的。在这种情况下,服务器将需要一些时间来收集其数据。一旦数据可用,它将创建一个响应,并将该数据与响应一起发送给客户端。所以,在这里,服务器收集所有的数据,一旦准备好了,它就把所有的数据发送给客户端。这就是 "承诺 "的工作方式。
Promise向我们承诺了一些数据,它在一段时间内向我们提供数据,一旦完整的数据准备好了,它就提供数据。这就是Promise的工作方式,也是对异步数据的处理。
一个Observable是如何处理异步数据的?
比方说,我们正在向服务器发出HTTP请求,从数据库中获取所有的用户,这样服务器就会从数据库或Web API中收集数据。观察者将不会等待完整的数据出现。
一个Observable将数据流化,所以它将以数据包的形式发送数据;当部分数据可用时,它将发送数据,然后再次收集其余的数据并将其与响应一起发送。
它分块发送数据。它不是在等待所有的数据,然后一次性发送数据,它是在流式发送数据,这就是Promise和Observable的区别所在
Rxjs有两个主要角色:Observable,数据流,以及观察者,它将使用这些数据。为了让这个观察者立即使用这个可观察者的数据,观察者必须订阅这个可观察者。因此,我们也可以说观察者是观察者的订阅者。
import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
title = 'rxjs';
myObservable = new Observable((observer) =>{
console.log('observable')
// Emit some data
// to emit the data on this observer, we can call next()
observer.next("1")
observer.next("2")
observer.next("3")
observer.next("4")
});
// The observable will only emit the data if it has subscriber, so let's create a subscriber for myObservable
ngOnInit(){
// the subscribe() takes 3 optional parameters and these are callback()
this.myObservable.subscribe((val) => {
console.log(val,"::val");
});
// the next parameter is a callback() & it gets executed every time the next() returns a value
// in this example we are subscribing myObservable, this next callback() will be called 4 times
}
}

在这里,我们可以看到,数据已经被一个一个地流出来了。这就是观测器的工作原理。
雇用具有无可比拟的灵活性的Java开发人员
Rxjs中的操作符。
在处理RxJs时,我们经常使用操作符,所以了解什么是操作符以及如何在Observable上使用操作符很重要。所以,RxJs中的操作符只是将一个Observable作为输入,将其转化为一个新的Observable,然后再返回的函数。
我们使用操作符来操作可观察数据流。让我们来看看RxJs的一些操作符。
RxJs中的Map()
地图运算符对来自服务器的数据进行转换。转化操作符基本上用于通过对每个项目应用一个函数来转化由观察者发出的项目。
正如我们在下面的代码片段中所看到的,我们正在使用'from'操作符创建一个可观察对象,对于from操作符,我们正在传递一个数组,该数组包含5个值。因此,从操作符创建的可观察变量将发射数组中的5个值,即1、2、4、6、8。在发射完所有的数据后,它还将发射一个完整的信号,因为我们已经用这个操作符创建了这个可观察变量。
现在,使用一个操作符,我们可以转换这个可观察变量返回的数据,然后我们可以用转换后的数据返回一个新的可观察变量。所以,这个可观察变量返回1、2、4、6、8。现在,我们想要的是,我们要对这个观测器所发出的数据进行转换。
比方说,我们想把这个观测器发出的每个值都乘以5,然后我们想返回转换后的数据。因此,新的可观察变量将返回5、10、20、30和40。这样的事情可以通过在这个可观察变量上使用操作符来实现。所以,我们使用map运算符来实现这个目的。
map操作符是一个以回调函数作为参数的函数。而这个回调函数将接收一个值。它将接收一个源观测器将发射的值,即myObservable。现在,这个映射操作符将返回一个新的观测器,而这个新的观测器将发射来自源观测器的转换数据。
因此,我们将其分配给一个新的属性,即transformedObs。因此,这个transformedObs将发射转换后的数据,即5、10、20、30、40。而且我们订阅了transformedObs而不是myObservable。我们将得到转换后的数据。
import { Component, OnInit } from '@angular/core';
import { from, Observable, of} from 'rxjs';
import { map } from 'rxjs/operators';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
title = 'rxjs';
arr1 = [1,2,4,6,8];
arr2 = ['R', 'A', 'S' ];
// Created an observable through from operator and passing an array
myObservable = from(this.arr1); // 1, 2, 4, 6, 8 => 5, 10, 20, 30, 40
transformedObs = this.myObservable.pipe(map((val) => {
return val * 5;
}))
ngOnInit(){
this.transformedObs.subscribe((val) => {
console.log(val,"::val");
},(error) => {
alert(error.message);
},() => {
alert('Observable has complete emitting values ')
});
}
}
这里是输出

RxJs中的Filter()。
一个过滤操作符根据指定的条件过滤源观测点发出的数据。比方说,从上述转换后的数据中,我们只想发射满足某个条件的数据。比方说,我们只想发射那些数据,这些数据要么>=30。
所以,这里我们只想发出30和40。所以基本上,我们想从这些数据中过滤一些给定条件的数据。为此,我们可以使用过滤器操作符。
import { Component, OnInit } from '@angular/core';
import { from, Observable, of} from 'rxjs';
import { map, filter } from 'rxjs/operators';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
title = 'rxjs';
arr1 = [1,2,4,6,8];
arr2 = ['R', 'A', 'S' ];
// Created an observable through from operator and passing an array
myObservable = from(this.arr1); // 1, 2, 4, 6, 8 => 5, 10, 20, 30, 40
transformedObs = this.myObservable.pipe(map((val) => {
return val * 5;
}))
// Here source observable i.e transformedObs is emitting => 5, 10, 20, 30, 40
filterObs = this.transformedObs.pipe(filter((val) => {
return val >= 30;
}))
ngOnInit(){
this.filterObs.subscribe((val) => {
console.log(val,"::val");
},(error) => {
alert(error.message);
},() => {
alert('Observable has complete emitting values ')
});
}
}
这里是输出。

这里我们可以看到,我们的输出满足了我们给定的条件,并且它返回了一个带有过滤数据的新的可观察变量
RxJs中的ForkJoin()
Forkjoin的工作原理类似于Javascript中的Promise.all。也就是说,让我们举个例子。
比方说,有两个观察变量。在这一点上,当两个观察变量都完成后,它将分别取第一和第二数据的最后值。所以它把最后的值结合起来,并给出结果。
我们可以在输入中给出一个可观察变量的数组,一旦所有的可观察变量都平行加载完毕,它就会发出数值。
ForkJoin()的用法。
- 并行调用多个远程API--例如,如果我们必须同时调用3个API。
- 调用混合观察变量--例如,如果我们必须获得一个API的结果和一个转换后的对象数据。
import { Component, OnInit } from '@angular/core';
import { forkJoin } from 'rxjs';
import { DataService } from '../data.service';
@Component({
selector: 'app-comp1',
templateUrl: './comp1.component.html',
styleUrls: ['./comp1.component.scss']
})
export class Comp1Component implements OnInit {
constructor( private dataService: DataService) { }
ngOnInit(): void {
}
onClick(){
// simulate 3 requests
forkJoin({
getUserById: this.dataService.getUserById(1), //user detail for id 1
getProductById: this.dataService.getProductById(1),//product detail by id 1
getCartById: this.dataService.getCartById(1) //cart
detail by id 1
})
.subscribe(({ getUserById, getProductById, getCartById }) => {
console.log('userDetails',getUserById);
console.log('productDetails', getProductById);
console.log('cartDetails', getCartById);
});
}
}

在这里,我们可以看到3个API已经被并行调用。

总结
RxJs为我们提供了更多的操作符,我们可以更深入地研究。在那之前,请享受阅读这篇文章吧