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, ... |