RxJS——调度器(Scheduler)
调度器
什么是调度器?调度器是当开始订阅时,控制通知推送的。它由三个部分组成。
- 调度是数据结构。它知道怎样在优先级或其他标准去存储和排队运行的任务
- 调度器是一个执行上下文。它表示任务在何时何地执行(例如,立即或是在回调机制中如 setTimeout 或 process.nextTick,又或是动画框架)
- 调度器有一个(虚拟)计时器。它提供一个 “时间” 的概念,通过在调度器的方法
now()。在特定的调度程序上调度,它只遵循计时器表示的时间。
调度器能让你在执行上下文定义 Observable 推送的通知给观察者
下面是一个例子,我们用一个简单的 Observable 来同步推送值 1,2,3,并且为了使用这些值,使用操作符 observeOn 到特定的 async 调度程序。
import { Observable, asyncScheduler } from 'rxjs';
import { observeOn } from 'rxjs/operators';
const observable = new Observable((observer) => {
observer.next(1);
observer.next(2);
observer.next(3);
observer.complete();
}).pipe(
observeOn(asyncScheduler)
);
console.log('just before subscribe');
observable.subscribe({
next(x) {
console.log('got value ' + x)
},
error(err) {
console.log('something wrong occurred: ' + err);
},
complete() {
console.log('done');
}
});
console.log('just after subscribe');
执行的输出:
just before subscribe
just after subscribe
got value 1
got value 2
got value 3
done
注意是如何通知 got value... 是在 just after subscribe 之后被推送的,它跟我们之前的默认的行为很相差很远的。这是因为 observeOn(asyncScheduler) 在 new Observable 和最终的观察者之间引入了一个代理观察者。我们来把之前的代码重命名一些标识再来看下:
import { Observable, asyncScheduler } from 'rxjs';
import { observeOn } from 'rxjs/operators';
var observable = new Observable((proxyObserver) => {
proxyObserver.next(1);
proxyObserver.next(2);
proxyObserver.next(3);
proxyObserver.complete();
}).pipe(
observeOn(asyncScheduler)
);
var finalObserver = {
next(x) {
console.log('got value ' + x)
},
error(err) {
console.error('something wrong occurred: ' + err);
},
complete() {
console.log('done');
}
};
console.log('just before subscribe');
observable.subscribe(finalObserver);
console.log('just after subscribe');
proxyObserver 在 observeOn(asyncScheduler) 中创建的,这个代理观察者里的 next(value) 函数大概像下面这样:
const proxyObserver = {
next(val) {
asyncScheduler.schedule(
(x) => finalObserver.next(x),
0, //延迟参数
val //这个值是从上面的 x 传过来的
);
},
// ...
}
the async 调度程序操作能还使用 setTimeout 或 setInterval,即使如果给定了 delay 的值是 0。通常,在 Javascript 中,setTimeout(fn, 0) 知道如何在下一个事件循环迭代最早运行函数 fn 。
调度器的方法 schedule() 有一个参数 delay,它指的是相对于调度器自己内部时钟的一个时间数字量。一个调度器的时间不需要有任何相关的实际时间。这个是一个暂时的操作像 delay 操作符一样而不是值实际的时间,但是时间是由调度器的时钟决定的。在测试中这特别有用,它这个虚拟的时间调度器也许用在伪装的真实时间,当在真正同步运行调度任务的时候。
调度器类型
async 调度器是 RsJS 众多调度器中内置的一个调度器。他们每一个都能被创建和返回,通过使用 Scheduler 对象的静态属性。
| SCHEDULER | PURPOSE |
|---|---|
null |
不传递任何调度器,通知以同步和递归的方式传递。这个将用于常量时间操作符或尾递归操作符。 |
queueScheduler |
对当前的事件框架队列调度(蹦床调度器)。迭代操作用这个 |
asapScheduler |
在微任务队列调度,它与 promises 的队列使用相同。基本上在当前 job 之后,但是在下一个 job 之前。异步约束使用这个 |
asyncScheduler |
用 setInterval 调度工作。在以时间为基础的操作用这个 |
animationFrameScheduler |
调度任务将会发生在下个浏览器内容重绘之前。能使用在平滑的创建浏览器动画 |
使用调度器
你也许早就在你的代码中使用 RsJS 的调度器,没有显式的说明使用的调度器类型。这是因为所有的处理并发的 Observable 操作符都有可选的调度器。如果你不提供调度器,RxJS 通过使用最小并发原则将会选择一个默认的调度器。这就是说最少并发的调度器需要安全的选择操作符。例如,返回一个有限和少量的 Observable 的操作符,RxJS 不使用调度器,例如 null 或 undefined。对于返回一个可能很大的或者无限的消息,那么就会使用 queue 调度器。对于使用时间的的操作符,那么就会用 async。
因为 RxJS 使用最少并发调度器,你可以选择一个不同的调度器,如果你想以性能为目的来引入并发。为了指定一个特定的调度器,你可以送那些操作符方法传递调度器,例如 from([10, 20, 30], asyncShceduler)
静态创建操作符通常将一个调度器作为参数传递。例如,from([10, 20, 30]) 允许你当推送每一个从 array 转化的通知时指定一个调度器。它通常是操作符上的最后一个参数。下面的静态创建操作符都会传递一个调度器参数:
bindCallbackbindNodeCallbackcombineLatestconcatemptyfromfromPromiseintervalmergeofrangethrowtimer
上下文将会调用 subscribe() 来用 subscribeOn 调度。subscribe 默认会在 Observable 调用,它将会同步和立即的方式调用。然而,你也许要延迟或在给定的调度器调度实际的订阅,使用操作符的 subscribeOn(scheduler) 的实例,里面的 scheduler 就是你要提供的参数。
使用 observeOn 来调度上下文将推送的通知。就像我们看到的一样,实例操作符 observeOn(scheduler) 在源 Observable 和 目标观察者之间引入 Observer 中间者,这个中介者调度器通过你给定的 shceduler 对目标观察者调用。
实例操作符传递一个调度器作为参数。
时间相关操作符像 bufferTime,debounceTime,delay,sampleTime,throttleTime,timeInterval,timeout,timeoutWith,windowTime 最后一个参数全都带一个调度器参数,以及其他操作符默认都会在 asyncScheduler 。
其他实例传调度器作为参数的操作符:cache,combineLatest,concat,merge,expand,publishReplay,startWith。
注意到 cache 和 publishReplay 这两个都接受一个调取器,因为他们都使用 ReplaySubject。ReplaySubject 构造函数传递一个可选的调度器作为最后一个参数,因为 ReplaySubject 能处理时间,它只有在调度器的上下文中才会有意义。ReplaySubject 默认使用 queue 调度器提供一个时钟。
PS:RxJS 系列文章同步至 https://github.com/MarsonShine/JavascriptStudy/tree/master/src/rxjs/docs
RxJS——调度器(Scheduler)的更多相关文章
- Cocos2d-X3.0 刨根问底(六)----- 调度器Scheduler类源码分析
上一章,我们分析Node类的源码,在Node类里面耦合了一个 Scheduler 类的对象,这章我们就来剖析Cocos2d-x的调度器 Scheduler 类的源码,从源码中去了解它的实现与应用方法. ...
- scrapy-redis(调度器Scheduler源码分析)
settings里面的配置:'''当下面配置了这个(scrapy-redis)时候,下面的调度器已经配置在scrapy-redis里面了'''##########连接配置######## REDIS_ ...
- pyspider源码解读--调度器scheduler.py
pyspider源码解读--调度器scheduler.py scheduler.py首先从pyspider的根目录下找到/pyspider/scheduler/scheduler.py其中定义了四个类 ...
- (5)调度器(scheduler)
继承关系 原理介绍 Cocos2d-x调度器为游戏提供定时事件和定时调用服务.所有Node对象都知道如何调度和取消调度事件,使用调度器有几个好处: 每当Node不再可见或已从场景中移除时,调度器会停止 ...
- cocos2dx调度器(scheduler)
调度器(scheduler) http://cn.cocos2d-x.org/article/index?type=cocos2d-x&url=/doc/cocos-docs-master/m ...
- 7.k8s.调度器scheduler 亲和性、污点
#k8s. 调度器scheduler 亲和性.污点 默认调度过程:预选 Predicates (过滤节点) --> 优选 Priorities(优先级排序) --> 优先级最高节点 实际使 ...
- 【Cocos2d-x 3.x】 调度器Scheduler类源码分析
非个人的全部理解,部分摘自cocos官网教程,感谢cocos官网. 在<CCScheduler.h>头文件中,定义了关于调度器的五个类:Timer,TimerTargetSelector, ...
- Yarn 组件的指挥部 – 调度器Scheduler
linux基础 为hadoop集群的搭建扫清了障碍,也为内存的管理,文件系统的管理扫清了障碍 接着到Hadoop的阶段,首先做集群的安装,深入到使用这两个核心的组件,分布式文件系统HDFS,解决大量数 ...
- hadoop之 Yarn 调度器Scheduler详解
概述 集群资源是非常有限的,在多用户.多任务环境下,需要有一个协调者,来保证在有限资源或业务约束下有序调度任务,YARN资源调度器就是这个协调者. YARN调度器有多种实现,自带的调度器为Capaci ...
随机推荐
- 靶场sql注入练手----sqlmap篇(纯手打)
靶场地址:封神台 方法一.首先尝试手工找注入点判断 第一步,判断是否存在sql注入漏洞 构造 ?id=1 and 1=1 ,回车,页面返回正常 构造 ?id=1 and 1=2 ,回车,页面不正常,初 ...
- (转)Qt中文手册 之 QApplication
QApplication管理GUI程序的控制流和主要设置. QApplication包含由窗口系统和其他来源处理过和发送过的主事件循环.它也处理应用程序的初始化和收尾工作,并提供对话管理.QAppli ...
- 第02组 Alpha冲刺(2/6)
队名:無駄無駄 组长博客 作业博客 组员情况 张越洋 过去两天完成了哪些任务 任务分配.进度监督 提交记录(全组共用) 接下来的计划 沟通前后端成员,监督.提醒他们尽快完成各自的进度 还剩下哪些任务 ...
- 团队作业第五次—项目冲刺-Day1
Day1 项目相关 作业相关 具体描述 所属班级 2019秋福大软件工程实践Z班 作业要求 团队作业第五次-项目冲刺 作业正文 hunter--冲刺集合 团队名称 hunter小组 作业目标 最终做出 ...
- JavaScript开发小技巧
总结一些能够提高开发效率的JS技巧 1.过滤唯一值 Set类型是在ES6中新增的,它类似于数组,但是成员的值都是唯一的,没有重复的值.结合扩展运算符(...)我们可以创建一个新的数组,达到过滤原数组重 ...
- spring&pom两种获取profile的方式
一.原理: 1.实现ApplicationContextAware(当一个类实现了ApplicationContextAware这个接口之后,这个类就可以通过setApplicationContext ...
- Alpha冲刺——测试篇
课程信息 课程 软件工程1916|W(福州大学) 团队名称 修!咻咻! 作业要求 项目Alpha冲刺 团队目标 切实可行的计算机协会维修预约平台 团队信息 队员学号 队员姓名 个人博客地址 备注 22 ...
- spring boot 从开发到部署(二)—重启服务
上篇中,我们开发并部署上线了一个 spring boot 项目.现在需要编写服务重启脚本,保证服务器重启后能够自动的运行我们的项目. /home/web/sprint-web/restart-happ ...
- 【C++】内联函数(inline)和宏定义(# define)的优劣及其区别
一.宏定义:# define 1.为什么要使用宏? 因为调用宏比调用函数更有效率,函数的调用必须要将程序的执行顺序转移到函数所存放的内存地址中,将函数程序内容执行完后,再返回到执行该函数前的地方,这种 ...
- Java注解及其原理以及分析spring注解解析源码
注解的定义 注解是那些插入到源代码中,使用其他工具可以对其进行处理的标签. 注解不会改变程序的编译方式:Java编译器对于包含注解和不包含注解的代码会生成相同的虚拟机指令. 在Java中,注解是被当做 ...