Introduction
RxJS中有许多创建Observable的方法,如from、of、interval等,本文一一介绍。
from
from方法可以将一个数组、类数组对象、Promise、可迭代对象、Observable-like对象转换为Observable。
将数组转换为Observable
RxJS社区有一个约定,以$结尾的变量代表一个Observable对象。下面的例子将一个数组转换为Observable。
1 | import { from } from 'rxjs'; |
上面的代码可以简化为:
1 | import { from } from 'rxjs'; |
将Promise转换为Observable
下面的例子将一个Promise对象转换为Observable。
1 | const p = new Promise((resolve) => { |
将可迭代对象转换为Observable
其实数组就是可迭代对象,所以前面数组的例子已经包含该例子,下面的例子将一个可迭代对象转换为Observable。
1 | function* generate123() { |
使用asapScheduler
使用asapScheduler可以让from方法在当前任务队列的末尾执行,下面的例子展示了如何使用asapScheduler。你知道以下代码输出什么吗?如果不加asapScheduler,输出会是什么?
1 | console.log('from start...'); |
以上代码输出如下:
1 | from start... |
如果去掉asapScheduler,则from同步执行,输出如下:
1 | from start... |
from的以下书写方式已经被废弃,将在RxJS 8中移除.
1 | from([1, 2, 3], asapScheduler).subscribe(console.log); |
推荐使用下面的方式,详情看这里
1 | scheduled([1, 2, 3], asapScheduler).subscribe(console.log); |
将Dom事件转换为Observable
使用fromEvent方法可以将Dom事件转换为Observable。
以下代码监听document的click事件,当点击document时,会在控制台输出clicked!。
1 | <html> |
默认情况下,浏览器的事件模型是冒泡模型,也可以改为捕获模型,只需要传递{ capture: true }作为fromEvent的第三个参数即可。
1 | fromEvent(document, "click", { capture: true }).subscribe(() => { |
of
of把输入的值转换为Observable。与from不同的是,of不会做任何flatten操作,它会把输入的值当做一个整体。这一点体现在数组上,from会把数组的每个元素当做一个值,而of会把整个数组当做一个值。
1 | import { of, from } from 'rxjs'; |
of通常用在要一次性生成多个值的场景,比如下面的例子:
1 | import { of } from 'rxjs'; |
range
Emit a sequence of numbers in a range.
在一个范围内生成一个Observable。range方法有三个参数,分别是start、count和scheduler。start表示起始值,count表示生成的个数,scheduler表示调度器。
1 | import { range } from 'rxjs'; |
interval
interval方法会每隔一段时间发出一个递增的数字。interval方法有一个参数period,表示时间间隔,单位是毫秒。interval默认使用asyncScheduler。
1 | import { interval } from 'rxjs'; |
有三点需要注意:
interval方法是异步的,默认使用asyncScheduler。interval方法会从0开始发出数字。interval方法第不是立即执行的,而是在第一个时间间隔之后执行。
以下代码输出什么?
1 | console.log('interval start...'); |
答:因为interval默认使用asyncScheduler,所以interval方法是异步的,所以interval start...和interval end...会先输出,然后再输出0, 1, 2, 3, 4, ...。
timer
可以将timer看成是高配版的interval,为啥这么说呢?因为interval只能设置时间间隔,却无法控制开始时间(interval的开始时间就是其时间间隔),而timer既能控制间隔时间,也能控制开始时间。
来看这样一个需求,每个1秒产生一个数字(从0开始),但是要求第一个数字立即产生,而不是等待1秒。interval无法满足这个需求,但是timer可以。
1 | import { timer } from 'rxjs'; |
timer方法的第一个参数就是开始时间,除了可以指定一个具体的毫秒数之外,还可以指定一个Date对象,表示在指定的时间开始。
1 | timer(new Date(2024, 11, 28, 17, 0, 0), 1000).subscribe(console.log); // 0, 1, 2, 3, 4, ... |