{"id":29195362,"url":"https://github.com/sullay/web-scheduler","last_synced_at":"2025-09-13T05:34:43.791Z","repository":{"id":198222228,"uuid":"700485996","full_name":"sullay/web-scheduler","owner":"sullay","description":null,"archived":false,"fork":false,"pushed_at":"2024-06-22T09:29:32.000Z","size":130,"stargazers_count":47,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-28T09:09:19.107Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sullay.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-10-04T17:25:50.000Z","updated_at":"2024-12-03T18:54:39.000Z","dependencies_parsed_at":"2024-10-23T03:35:48.465Z","dependency_job_id":"371c5ac9-ce98-49e2-a719-9e1d6d2a02ec","html_url":"https://github.com/sullay/web-scheduler","commit_stats":{"total_commits":21,"total_committers":3,"mean_commits":7.0,"dds":0.09523809523809523,"last_synced_commit":"dc40d4bf85edf544b689d8250c7458b1144fd7d2"},"previous_names":["sullay/web-scheduler"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/sullay/web-scheduler","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sullay%2Fweb-scheduler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sullay%2Fweb-scheduler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sullay%2Fweb-scheduler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sullay%2Fweb-scheduler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sullay","download_url":"https://codeload.github.com/sullay/web-scheduler/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sullay%2Fweb-scheduler/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264431743,"owners_count":23607305,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-07-02T05:03:15.053Z","updated_at":"2025-07-24T14:02:14.575Z","avatar_url":"https://github.com/sullay.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# WEB SCHEDULER\n\nWEB SCHEDULER 是一个应用于浏览器环境的任务调度工具。用于管理系统运行过程中的各类任务，支持大量、高频、高耗时任务的场景，帮助提高系统性能，提升系统流畅度。\n\n## 安装\n\n你可以使用 npm、pnpm或者yarn 进行安装：\n\n```bash\n    npm install web-sheduler\n\n    yarn add web-sheduler\n\n    pnpm add web-sheduler\n```\n\n## 使用\n\n支持多种任务调度模式，对应浏览器运行的各个阶段，支持自定应任务调度。\n\n![浏览器渲染生命周期](./docs/images/scheduler.webp)\n\n### TaskList\n\n基于哈希表和双向跳表的任务列表，\n\n`TaskList` 是一个 JavaScript 类，用于管理任务列表，用于定制化任务调度场景。它基于哈希表和双向跳表实现，允许你添加、删除和更新任务，并根据优先级和超时时间对任务进行排序。后续所有任务调度器都基于此任务列表开发。\n\n`定制化任务调度场景才会用到，正常使用只需了解运行逻辑即可。`\n\n#### TaskList示例\n\n```ts\nimport { TaskList, PRIORITY_TYPE } from 'web-scheduler';\n\n// 创建任务列表\nconst taskList = new TaskList();\n\n// 添加任务\ntaskList.put(() =\u003e conosle.log(\"任务1\"));\n\ntaskList.put(() =\u003e conosle.log(\"任务2\"), { \n    key: '任务2', \n    priority: PRIORITY_TYPE.NORMAL, \n    callback:() =\u003e console.log(\"任务2 回调函数\") \n});\n\n// 取出首个任务并执行\nconst task = taskList.shift()\ntask?.run()\n\n// 更新任务\ntaskList.put(() =\u003e conosle.log(\"更新任务2\"), {\n    key: '任务2',\n    priority: PRIORITY_TYPE.LOW, \n    callback:() =\u003e console.log(\"更新任务2 回调函数\") \n});\n\n// 判断任务队列是否为空\ntaskList.isEmpty();\n\n// 检查任务是否存在\ntaskList.has('任务1'); // 输出：true/false\n\n// 获取首个任务的超时时间\ntaskList.getFirstTimeOut()\n\n// 重新设置不同优先级对应的超时时间\n// 默认各优先级超时时间\nexport const DEFAULT_PRIORITY_TIMEOUT = {\n    [PRIORITY_TYPE.IMMEDIATE]: -1 as const,\n    [PRIORITY_TYPE.HIGH]: 250,\n    [PRIORITY_TYPE.NORMAL]: 1000,\n    [PRIORITY_TYPE.LOW]: 5000,\n    [PRIORITY_TYPE.IDLE]: 1073741823 as const\n}\n\ntaskList.setPriorityTimeout({\n    [PRIORITY_TYPE.HIGH]: 2500,\n    [PRIORITY_TYPE.NORMAL]: 10000,\n    [PRIORITY_TYPE.LOW]: 50000,\n})\n\n```\n\n#### TaskList注意事项\n\n- 默认使用symbol当作key值，不需要更新任务的场景不需要设置options.key参数\n\n- 任务队列基于超时时间进行排序，优先级只影响任务的超时时间的设置\n\n- 默认支持的任务调度器中，会优先执行距离超时最近的任务，已超时任务会无视刷新率快速处理掉，自定义任务调度需要自行编写处理策略\n\n- 使用key值更新任务后，val会被替换掉所以并不保证一定会执行\n\n- 使用key值更新任务后，会合并新旧的callback回调，所以必须要确保执行的代码请使用callbak\n\n- 使用key值更新任务后，如果新的超时时间更紧急会向前移动任务，反之则继续使用旧任务的超时时间\n\n- 修改优先级对应的超时时间不影响先前插入的任务\n\n### AnimationFrameScheduler\n\n`AnimationFrameScheduler` 是一个基于 `requestAnimationFrame` 的任务调度器，适用于动画、布局计算。\n\n- 执行阶段：rAF\n- 时间分片时长：默认通过估算屏幕刷新率计算。例如fps为60hz，Math.floor(1000/{fps}/2) = 4ms\n- 已超时任务无视时间分片时长强制运行\n\n#### AnimationFrameScheduler示例\n\n```ts\nimport { animationFrameScheduler } from 'animation-frame-scheduler';\n\n// 设置优先级、时间分片时长\nawait animationFrameSchedular.setConfig ({ \n    priorityTimeoutParams: {\n        [PRIORITY_TYPE.HIGH]: 2500,\n        [PRIORITY_TYPE.NORMAL]: 10000,\n        [PRIORITY_TYPE.LOW]: 50000,\n    }, \n    frameDuration: 5\n}\n\n// 添加任务到调度器\nanimationFrameScheduler.pushTask(() =\u003e {\n  // 这里是任务的具体逻辑\n});\n\nanimationFrameScheduler.pushTask(() =\u003e conosle.log(\"任务2\"), { \n    key: '任务2', \n    priority: PRIORITY_TYPE.NORMAL, \n    callback:() =\u003e console.log(\"任务2 回调函数\") \n});\n```\n\n### SingleAnimationFrameScheduler\n\n`SingleAnimationFrameScheduler` 是一个基于 `requestAnimationFrame` 的任务调度器，它每帧只执行一个任务，通常用于逐帧操作动画或其他需要按帧处理的任务。这个调度器可以确保在每一帧中只执行一个任务，方便自定义动画的开发，并且避免卡顿和提供流畅的用户体验。\n\n- 执行阶段：rAF\n- 每一帧只执行一次，没有时间分片时长概念\n- 即使任务已经超时，也会按照排序逐帧执行\n\n#### SingleAnimationFrameScheduler示例\n\n```ts\nimport {\n    singleAnimationFrameScheduler,\n} from 'web-scheduler'\n\nconst circle = document.querySelector('.circle') as HTMLElement;\n\n\ncircle.onclick = ()=\u003e{\n    for(let i=0; i\u003c 1000; i++){\n        singleAnimationFrameScheduler.pushTask(()=\u003e{\n            circle.style.width = `${i}px`\n            circle.style.height = `${i}px`\n        })\n    }\n}\n```\n\n### ImmediateScheduler\n\n`ImmediateScheduler` 是一个基于 `setImmediate` 的任务调度器，适合用于操作 DOM 元素以及执行其他 JavaScript 功能。\n\n- 执行阶段：JS\n- 时间分片时长：默认通过估算屏幕刷新率计算。例如fps为60hz，Math.floor(1000/{fps}/2) = 4ms\n- 已超时任务无视时间分片时长强制运行\n\n#### ImmediateScheduler示例\n\n```ts\nimport { immediateScheduler } from 'web-scheduler';\n\nfunction fetchData() {\n  // 模拟异步数据请求\n}\n\nfunction processData() {\n  // 处理数据\n  console.log('Data processed.');\n}\n\n// 启动任务\nimmediateScheduler.pushTask(fetchData);\nimmediateScheduler.pushTask(processData);\n\n```\n\n### IdleFrameScheduler\n\n`IdleFrameScheduler` 是一个基于 `requestIdleCallback` 的任务调度器，它允许你在浏览器的每一帧的空闲时间执行任务。这样可以最大程度地利用计算资源，特别适用于执行非关键任务。\n\n- 执行阶段：Paint之后执行\n- 时间分片时长：浏览器渲染一帧全部工作完成后的剩余时长 （1000/{fps} - 已用时长）\n- 已超时任务无视时间分片时长强制运行\n- 主要用于执行非关键任务，以充分利用浏览器的空闲时间。不建议将关键任务放在此调度器中，如果一直没有空闲时间，任务会超时后才能执行。\n\n#### IdleFrameScheduler示例\n\n```ts\nimport { idleFrameScheduler } from 'web-scheduler';\n\nfunction log() {\n    // 打印日志\n}\nfunction report() {\n    // 上报数据\n}\n\n// 启动任务\nidleFrameScheduler.pushTask(log);\nidleFrameScheduler.pushTask(report);\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsullay%2Fweb-scheduler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsullay%2Fweb-scheduler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsullay%2Fweb-scheduler/lists"}