RxJS 中的调度器 ( Schedulers ) 是用来控制事件发出的顺序和速度的(发送给观察者的)。
const a$ = Rx.Observable.of(1, 2);
const b$ = Rx.Observable.of(10);
const c$ = Rx.Observable.combineLatest(a$, b$, (a, b) => a + b);
c$.subscribe(c => console.log(c));
默认情况下,RxJS 使用所谓的递归调度器。下面是它的工作原理:
发出的顺序为 1, 2, 10。
咱们在 a$ 上使用 asap 调度器来让其“慢下来”:
const a$ = Rx.Observable.from([1, 2], Rx.Scheduler.asap); // 新代码
const b$ = Rx.Observable.of(10);
const c$ = Rx.Observable.combineLatest(a$, b$, (a, b) => a + b);
c$.subscribe(c => console.log(c))
发出的顺序为 10, 1, 2。
咱们可以为 b$ 也自定义调度器:
const a$ = Rx.Observable.from([1, 2], Rx.Scheduler.asap);
const b$ = Rx.Observable.from([10], Rx.Scheduler.asap); // 新代码
const c$ = Rx.Observable.combineLatest(a$, b$, (a, b) => a + b);
c$.subscribe(c => console.log(c));
发出的顺序为 1, 10, 2。
调度器还可以让事件的发出变得更快,同时保持发出的顺序不变。例如,RxJS 的 TestScheduler
可以使 Observable.interval(1000).take(10)
被订阅时进行同步执行,而不需要花费10秒钟来完成:
Rx.Observable.interval(1000, new Rx.TestScheduler()).take(10)
调度器 | 目的 |
---|---|
null | 不传递任何调度器的话,会以同步递归的方式发送通知。用于定时操作或尾递归操作。 |
Rx.Scheduler.queue | 当前事件帧中的队列调度(蹦床调度器)。用于迭代操作。 |
Rx.Scheduler.asap | 微任务的队列调度,它使用可用的最快速的传输机制,比如 Node.js 的 process.nextTick() 或 Web Worker 的 MessageChannel 或 setTimeout 或其他。用于异步转换。 |
Rx.Scheduler.async | 使用 setInterval 的调度。用于基于时间的操作符。 |
这是官网给出的类型,大家看看就行。
对于返回有限和少量消息的 observable 的操作符,RxJS 不使用调度器,即 null 或 undefined 。对于返回潜在大量的或无限数量的消息的操作符,使用 queue 调度器。对于使用定时器的操作符,使用 asap或aysnc 调度器。
静态创建操作符通常可以接收调度器作为参数。
使用 subscribeOn 来调度 subscribe() 调用在什么样的上下文中执行。
使用 observeOn 来调度发送通知的的上下文。
实例操作符可能会接收调度器作为参数。
像 bufferTime、debounceTime、delay、auditTime、sampleTime、throttleTime、timeInterval、timeout、timeoutWith、windowTime 这样时间相关的操作符全部接收调度器作为最后的参数,并且默认的操作是在 Rx.Scheduler.async 调度器上。
注意,cache 和 publishReplay 都接收调度器是因为它们使用了 ReplaySubject 。ReplaySubjects 的构造函数接收一个可选的调度器作为最后的参数,因为 ReplaySubject 可能会处理时间,这只在调度器的上下文中才有意义。默认情况下,ReplaySubject 使用 queue 调度器来提供时钟。
var a, b = 1, c =2;
a = b + c;
console.log('b=' + b);
console.log('c=' + c);
console.log('a=' + a);
b = 3;
c = 2;
console.log('a=' + a);
这段中,我们如果想让a输出为5,就是当b和c二次赋值后a的值是不会自动更新为5的。我们称这种方式为命令式编程。
var b$ = Rx.Observable.from([1, 3]);
var c$ = Rx.Observable.from([2, 2]);
var a$ = Rx.Observable.zip(b$, c$, (b, c) => {
console.log('b=' + b);
console.log('c=' + c);
return b + c;
});
a$.subscribe(a => console.log('a=' + a));
BMI:体重公斤数除以身高米数平方得出的数字。
成人的BMI数值:
过轻:低于18.5
正常:18.5-23.9
过重:24-27
肥胖:28-32
非常肥胖, 高于32
Weight: kg
Height: cm
Your BMI is
let weight = document.getElementById('weight');
let height = document.getElementById('height');
let bmi = document.getElementById('bmi');
let weight$ = Rx.Observable
.fromEvent(weight, 'input')
.pluck('target', 'value');
let height$ = Rx.Observable
.fromEvent(height, 'input')
.pluck('target', 'value');
let bmi$ = Rx.Observable
.combineLatest(weight$, height$, (w, h) => w/(h*h/100/100));
bmi$.subscribe(b => bmi.innerHTML=b);
JS Bin
let todo = document.getElementById('todo');
let input$ = Rx.Observable.fromEvent(todo, 'keyup');
input$.subscribe(input => console.log(input.target.value));
let todo = document.getElementById('todo');
let input$ = Rx.Observable.fromEvent(todo, 'keyup');
input$
.filter(ev=>ev.keyCode===32)
.subscribe(ev=>console.log(ev.target.value));
JS Bin
let todo = document.getElementById('todo');
let input$ = Rx.Observable.fromEvent(todo, 'keyup');
input$
.map(ev=>ev.target.value*10)
.subscribe(value=>console.log(value));
let todo = document.getElementById('todo');
let input$ = Rx.Observable.fromEvent(todo, 'keyup').pluck('target', 'value');
let addBtn = document.getElementById('addBtn');
let buttonClick$ = Rx.Observable
.fromEvent(addBtn, 'click')
.mapTo('clicked');
Rx.Observable.combineLatest(buttonClick$, input$, (ev, input)=>{
return {
ev: ev,
input: input
}
}).subscribe(value => console.log(value))
注:
这些都可以帮助我们来完成请求。
基本用法 :
import { Component, OnDestroy } from '@angular/core';
import { Observable, Subscription } from 'rxjs’;
import 'rxjs/add/observable/interval';
@Component({
selector: 'app-playground',
templateUrl: './playground.component.html',
styleUrls: ['./playground.component.css']
})
export class PlaygroundComponent implements OnDestroy{
clock: number;
subscription: Subscription;
constructor() {
this.subscription = Observable.interval(1000)
.do(_ => console.log('observable created'))
.subscribe(value => this.clock= value);
}
ngOnDestroy(){
if(this.subscription !== undefined)
this.subscription.unsubscribe();
}
}
{{clock}}
注:这段代码还可以有另一种写法
private alive: boolean = true;
.takeWhile(() => this.alive)
this.alive = false;
管道用法:
import { Component } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/interval';
@Component({
selector: 'app-objdemo',
templateUrl: './objdemo.component.html',
styleUrls: ['./objdemo.component.scss']
})
export class ObjdemoComponent {
clock = Observable.interval(1000).do(_ => console.log('observable created'));
constructor() { }
}
{{clock | async}}
message.service.ts
import { Injectable } from '@angular/core';
import {Observable, Subject} from 'rxjs';
@Injectable()
export class MessageService {
private subject = new Subject();
sendMessage(message: string) {
this.subject.next({ text: message });
}
clearMessage() {
this.subject.next();
}
getMessage(): Observable {
return this.subject.asObservable();
}
}
注:asObservable
函数是为了把一个 Observable
对象包装起来并安全的分享给其他人使用。
message.component.ts
import { Component } from '@angular/core';
import { Subscription } from 'rxjs';
import { MessageService } from '../ message / message.service';
@Component({
moduleId: module.id,
templateUrl: 'objdemo.component.html'
})
export class ObjdemoComponent {
message: any;
subscription: Subscription;
constructor(private messageService: MessageService) {
this.subscription = this.messageService.getMessage()
.subscribe(message => {
this.message = message ? message.text : ‘’;
});
}
sendMessage(): void {
this.messageService.sendMessage(‘Message!');
}
clearMessage(): void { // 清除消息
this.messageService.clearMessage();
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
message.component.html
{{message}}
members.service.ts
import { Injectable } from '@angular/core';
import { Headers, Http } from '@angular/http';
import { Observable, ObservableInput } from "rxjs/Observable";
@Injectable()
export class CommonService {
private headers = new Headers({ 'Content-Type': 'application/json' });
constructor(private http: Http) { }
get(url): Observable {
return this.http.get(url)
.map(response => response.json())
.catch(this.handleError);
}}
public handleError(error:any): ObservableInput {
return Observable.throw(error);
}
}
members.commonet.ts
import { Component } from '@angular/core';
import { MembersService } from '../../members.service';
import { AppSettings } from "../../app.settings";
@Component({
selector: 'app-members’,
templateUrl: './members.component.html',
styleUrls: ['./members.component.scss']
})
export class MembersComponent{
private membersUrl = `${AppSettings.env_vars.API_URL}/members`;
rows = [];
constructor(private membersService MembersService ) {
this. getMembers();
} }
getMembers(): void {
this. membersService.get(this.membersUrl)
.subscribe(members => {
this.rows = members;
} , error => { console.log(error) }, () => { });
}
注:文章先总结到这,有遗漏的要点欢迎补充!
1、程序员分类目录导航
2、Rxjs入门1
3、Rxjs入门2
4、Rxjs入门3