04_实现调度执行

什么是可调度?所谓可调度,指的是当 trigger 动作触发副作用函数重新执行的时候,有能力决定副作用函数执行的时机、次数以及方式

副作用函数执行方式

示例代码:

const obj = { a: 1 } 
const objProxy = new Proxy(obj, /* ... */)effect(() => {console.log(objProxy.a)
})objProxy.a++console.log('结束了')

这段案例代码的输出顺序如图:

在这里插入图片描述

如果想将输出的顺序做一下修改,如下:

1
结束了
2

这样的顺序应该如何实现呢?如果在一个简单的输出里面,我们想实现这一点,只需要将这个第二次打印 objProxy.a 的函数放入一个异步队列执行即可。这样就会先执行同步代码,打印 ‘结束了’,这就是决定这个 副作用函数的执行时机。

这时候就需要有一个调度系统,调度系统我们可以通过参数来进行决定是否开启,那么首先就要定义好这个参数的接收,如下:

// 添加 options 为第二个参数
function effect(fn, options) {const effectFn = () => {activeFn = effectFncleanup(effectFn)effectStack.push(effectFn)fn()effectStack.pop()activeFn = effectStack[effectStack.length - 1]}// 将配置项挂载到effectFn上effectFn.options = optionseffectFn.deps = []effectFn()
}

然后有了参数之后,我们就需要传入,代码如下:

effect(() => {console.log(objProxy.a)},{// 传入一个调度器参数//  -  fn 就行是需要执行的副作用函数scheduler(fn) {console.log('调度器执行', fn)}}
)

传参和接收都有了,那么剩下的就是执行,而上述分析中,我们就知道了,触发是在 trigger 函数内,所以我们只需要在这里执行副作用函数时,进行一个判断,如果存在调度器,则调用调度器执行副作用函数,代码如下:

function trigger(target, key) {let depsMap = targetMap.get(target)if (!depsMap) returnlet deps = depsMap.get(key)if (!deps) returnconst effetsToRun = new Set()deps.forEach(effectFn => {if (effectFn !== activeFn) {effetsToRun.add(effectFn)}})effetsToRun.forEach(fn => {// 如果有调度器,则调用调度器执行if (fn.options && fn.options.scheduler) {fn.options.scheduler(fn)} else {fn()}})
}

此时我们如果想实现改变这个输出顺序就很简单了,只需要在触发的时候,加入异步队列即可,代码如下:

effect(() => {console.log(objProxy.a)},{scheduler(fn) {// 使用定时器加入异步任务setTimeout(fn)}}
)objProxy.a++console.log('结束了')

执行结果如图:

在这里插入图片描述

控制副作用函数的执行次数

案例如下:

effect(() => {console.log(objProxy.a)
}, {})objProxy.a++
objProxy.a++

这段代码输出结果显而易见 1、2、3,那我们改变这个执行次数的意义何在呢?从1自增到3,2就表示是一个过渡状态,在有些场景中,我们可能并不关系这个过渡的状态,只关心最后的结果,此时 2 的输出的就多余的,那么基于调度器,我们就可以很容易的实现这一点,代码如下:

// 定义一个任务队列,采用 Set 数据结构,因为 Set 中的元素是唯一的,可以避免重复添加任务
const jobQueue = new Set()
// 创建一个 promise 实例,用于将任务添加到微任务队列
const p = Promise.resolve()// 是否正在刷新队列
let isFlushing = false
// 刷新队列函数
function flushJob() {// 如果正在刷新队列,则不做任何处理if (isFlushing) return// 更改刷新状态isFlushing = true// 加入一个微任务p.then(() => {// 将 jobQueue 中的任务依次执行jobQueue.forEach(job => job())}).finally(() => {// 任务执行完毕后,重置 isFlushing 为 falseisFlushing = false})
}effect(() => {console.log(objProxy.a)},{scheduler(fn) {// 每次 objProxy.a 变化时,都会触发调度器//  - jobQueue 是一个 Set 结构,所以不管触发多少次,只会添加一次任务jobQueue.add(fn)// 调用 flushJob 函数,将任务添加到微任务队列flushJob()}}
)objProxy.a++
objProxy.a++

我们先查看一下执行的结果,如图:

在这里插入图片描述

这段代码,还是比较好理解的,我们来简单的论述一下这个执行的过程,连续对 a 进行两次自增的操作,就会同步切连续的触发两次调度器,那么此时,就会将副作用函数连续加入两次,但是我们采用的是 Set 结果,所以只会加入一次。而 flushJob 第一次调用的时候,会将 isFlushing 设置为 true,并创建一个微任务,这个微任务会循环遍历执行 jobQueue 里面的任务,而由于是微任务,将在所有同步任务执行完成之后才会执行,所以暂时不会进行遍历 jobQueue,而这个微任务执行完成之后才会将 isFlushing 改为 false,所以当第二次调用 flushJob 函数执行的时候,isFlushing 还是 true,自然不会进行后续的逻辑,此时,同步任务执行完毕,就遍历执行 jobQueue 里面的任务,不过里面只存储了一个任务,所以只会执行一次副作用函数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/447581.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

02.顺序表、链表简述+对比

目录 一、线性表 二、顺序表 三、链表 四、顺序表和链表的区别 一、线性表 线性表(linear list)是n个具有相同特性的数据元素的有限序列(相同特性指都为整型int、字符型char或其它类型)。 线性表是一种在实际中广泛使用的数据…

雷池社区版配置遇到问题不要慌,查看本文解决

很多新人不太熟悉反向代理,所以导致配置站点出现问题 配置问题 记录常见的配置问题 配置后攻击测试没有拦截记录 检查访问请求有没有真实经过雷池 有很多新人配置站点后,真实的网站流量还是走的源站,导致雷池这边什么数据都没有 配置后…

软考《信息系统运行管理员》- 5.2 信息系统数据资源例行管理

5.2 信息系统数据资源例行管理 文章目录 5.2 信息系统数据资源例行管理数据资源例行管理计划数据资源载体的管理存储介质借用管理存储介质转储管理存储介质销毁管理 数据库例行维护健康检查数据库日志检查数据库一致性检查 数据库监测管理数据库备份与恢复数据库备份与恢复数据…

三子棋(C 语言)

目录 一、游戏设计的整体思路二、各个步骤的代码实现1. 菜单及循环选择的实现2. 棋盘的初始化和显示3. 轮流下棋及结果判断实现4. 结果判断实现 三、所有代码四、总结 一、游戏设计的整体思路 (1)提供一个菜单让玩家选择人机对战、玩家对战或者退出游戏…

生成式人工智能助长更复杂的网络攻击

网络安全公司 Keeper Security 表示,尽管黑客使用生成式人工智能使网络威胁更加频繁、更加复杂、更难以检测,但许多企业表示对此并未做好准备。 然而,据该公司表示,尽管各组织需要加强防御能力,但他们已经实施的许多基…

从调用NCCL到深入NCCL源码

本小白目前研究GPU多卡互连的方案,主要参考NCCL和RCCL进行学习,如有错误,请及时指正! 内容还在整理中,近期不断更新!! 背景介绍 在大模型高性能计算时会需要用到多卡(GPU&#xf…

接口性能测试,这个还真有用啊。

一、概述 性能测试按照不同视角,可以分为以下几类: a. 用户视角的性能 用户角度感受到的网站响应速度的快和慢。从用户在浏览器输入网址/打开应用,到整个页面呈现给用户的耗时。包含了用户端发送请求,服务端收到并执行请求&…

Python和MATLAB及C++和Fortran胶体粒子数学材料学显微镜学微观流变学及光学计算

🎯要点 二维成像拥挤胶体粒子检测算法粒子的局部结构和动力学分析椭圆粒子成链动态过程定量分析算法小颗粒的光散射和吸收活跃物质模拟群体行为提取粒子轨迹粘弹性,计算剪切模量计算悬浮液球形粒子多体流体动力学概率规划全息图跟踪和表征粒子位置、大小…

StableDiffusion|833种艺术家风格项目,提示词直接上手! AI绘画文生图直接抄!

大家好,我是画画的小强 众所周知,Stable Diffusion是一个强大的文生图模型,能够根据用户的文本描述生成高质量的图像。在这个过程中,提示词(Prompt)的选择和构造具有至关重要的作用。提示词是向模型描述你…

强化学习之Q-learning算法

前言: 在正文开始之前,首先给大家介绍一个不错的人工智能学习教程:https://www.captainbed.cn/bbs。其中包含了机器学习、深度学习、强化学习等系列教程,感兴趣的读者可以自行查阅。 一、算法介绍 Q-Learning是一种基于值函数的强…

山西农业大学20241015

02-VUE 一. Vue中常用的指令1. Vue指令概述2 Vue中指令的分类3 Vue中指令3.1 内容渲染指令3.2 条件渲染指令3.2.1 v-show3.2.2 v-if3.2.3 v-else 和 v-else-if 3.3 事件绑定指令 v-on--重要3.3.1 内联语句3.3.2 methods中的函数名 一. Vue中常用的指令 1. Vue指令概述 概念: 指…

STL --- list(C++)

本期鸡汤: “星光不负赶路人,时光不负有心人;你只管努力,剩下的交给时间。” 目录 1.list的介绍即使用 1.1list介绍 1.2list使用 1.2.1list构造 1.2.2list的iterator的使用 1.2.3list capacity 1.2.4list element access 1…

LeCun数十年经验之谈:视觉是建立AGI的核心,视频理解难点在哪?语言模型技术为何难以复用于视觉?

文字来源 | 夕小瑶科技说 AI寒武纪 大语言模型(LLM)已经接近人类水平,但视觉理解在世界范围似乎尚未突破,那么为何不能直接将LLM技术用于视觉?让AI看视频的难点在哪?如果语言是AGI必要的能力,为…

【Java 22 | 6】 深入解析Java 22 :记录(Records)增强详解

Java 22 对记录(Records)进行了重要的增强,进一步提升了这一特性在数据建模和类型安全方面的灵活性。以下是对记录类的详细介绍,包括基础概念、增强特性、使用场景、实际项目中的应用示例,以及示例代码。 1. 基础介绍…

使用js和canvas实现简单的网页贪吃蛇小游戏

玩法介绍 点击开始游戏后&#xff0c;使用键盘上的↑↓←→控制移动&#xff0c;吃到食物增加长度&#xff0c;碰到墙壁或碰到自身就游戏结束 代码实现 代码比较简单&#xff0c;直接阅读注释即可&#xff0c;复制即用 <!DOCTYPE html> <html lang"en"…

快速理解http的get和post

在网络通信中&#xff0c;HTTP 协议扮演着非常重要的角色&#xff0c;而不同的 HTTP 方法决定了客户端与服务器之间的交互方式。 这里讲一下最常用的两种方法——GET 和 POST。 一、GET 方法 GET 方法用于从服务器获取资源。 这就像去图书馆借书——你向图书馆请求一本特定的…

【JVM】内存分析工具JConsole/Visual VM

1 缘起 日常补充JVM调优&#xff0c;调优实践前需要学习一些理论做支撑&#xff0c; JVM调优三步&#xff1a;理论>GC分析>JVM调优&#xff0c; 我们会有一些玩笑话说&#xff0c;做了这么久Java开发&#xff0c;做过JVM调优吗&#xff1f; 做过&#xff0c;面试时。当然…

java中连接Mysql以及PreparedStatement如何防止sql注入

目录 JDBC 使用JDBC连接到MySQL 使用 Statement 使用 PreparedStatement Statement 和 PreparedStatement 区别 在 java 中如何连接到 MySQL 数据库&#xff0c;执行 SQL 查询&#xff0c;并处理查询结果&#xff1f; JDBC java 程序连接到 mysql&#xff0c;首先需要下…

2024年看项目管理软件与工程项目管理的奇妙融合

一、禅道在项目管理中的全面应用 禅道在产品管理方面&#xff0c;能够清晰地对产品的需求进行全方位管理。从需求的提出到详细信息的记录&#xff0c;再到状态、负责人以及完成进度的跟踪&#xff0c;都能有条不紊地进行。产品经理可以通过禅道制定合理的产品规划&#xff0c;…

实用宝典:元器件外贸独立站电子元件数据库设置完全手册

对于投身于元器件外贸领域的企业来说&#xff0c;如何建立一个既能凸显自身特色又具备高度功能性与良好用户体验的独立站&#xff1f;而在这一过程中&#xff0c;#电子元件数据库#作为独立站的核心要素之一&#xff0c;它的构建质量和管理方式又将如何直接影响网站的整体竞争力…