RxJS入门:用JavaScript反应式编程优雅处理异步数据流
最近在帮团队做前端项目重构遇到一个特别典型的场景页面里有多个联动筛选器用户每点一个下拉框就要重新请求接口、刷新列表、更新 URL 参数还得保证快速连续操作时不会把旧请求的结果覆盖到新请求上。代码写着写着就开始堆回调、堆状态标记逻辑一多连自己都绕晕了。后来把这块用 JavaScript 反应式编程的思路重写了一遍清晰度直接提升了一个档次。说白了一句话反应式编程就是把“数据变化”当成一条河流你只需要声明“当水流到这里时要做什么”不用再手动控制每一次水流的走向和开关。在 JavaScript 生态里最能代表这种思路的库就是 RxJS它也是 Angular 底层依赖的核心基础设施。这篇博文是这个系列的第一篇我会从最基础的概念讲起配合具体代码示例把 Observable、Observer、Subscription 这些词掰开揉碎讲清楚再带你写一个能直接跑起来的搜索防抖示例。适合刚接触响应式编程、或者之前看过 RxJS 但没看懂的人在实战中回味一下。1. 反应式编程到底在解决什么问题先说清楚一件事反应式编程不是 JavaScript 专属的概念也不是某个框架的特定功能。它是一套关于“如何处理异步数据流”的编程范式在 Java 里有 RxJava在 Kotlin 里有 FlowPython 里也有 ReactiveX 的实现。落到 JavaScript 里我们最常接触的就是 RxJS以及以 RxJS 为基础构建的框架机制。1.1 从传统命令式代码的痛点说起不知道你有没有过这种经历页面上有一个输入框用户输入的同时要实时搜索还要监听滚动事件来做懒加载同时 WebSocket 推送的数据也要更新页面状态。这三个需求如果都用传统命令式写法代码大概会长这样给输入框绑定input事件在回调里判断值是否变化再节流或防抖给滚动事件绑定回调计算滚动位置是否接近底部给 WebSocket 的message事件绑定回调解析数据后更新页面。每个回调里都在做类似的事情取数据、判断条件、改写某个状态、触发另一个操作。一旦操作之间有先后依赖比如“输入变化 → 防抖 → 请求接口 → 拿到结果后更新列表”就需要手动把每一步串联起来。这里面最容易翻车的点有两个一是异步竞态旧请求比新请求后返回导致数据覆盖二是状态同步多个数据源输入、滚动、推送之间互相影响改一处就牵动一处代码越写越乱。命令式代码不是不行而是当异步事件数量上升以后心智负担会指数级增长。你需要不断在心里模拟“如果 A 先发生、B 后发生会怎样反过来又会怎样”。这种“手动管理所有可能性”的方式本质上是把程序的控制流和数据流混在了一起。1.2 反应式编程的核心思想数据流与传播反应式编程换了一个角度把每个数据源都看作一条“流”Stream凡是要针对流做操作的地方就定义一个对流的“响应”。在 JavaScript 反应式编程的世界里这条流叫Observable意为“可以被观察的事物”。你订阅它它发射数据你不订阅它就什么都不做。这其实就是经典的观察者模式的升级版。普通观察者模式里发布者推数据订阅者接收数据双方通过事件机制解耦。而响应式编程在观察者模式之上加了三样东西时间维度的操作数据是有先后顺序的可以延迟、防抖、节流、超时处理流的组合能力多个流可以合并、串联、竞争、并行像管道一样拼接统一的错误处理错误本身也能沿着流传播可以在指定位置捕获并处理。所以你不需要写“如果请求失败就弹提示”这种散落在各处的逻辑你可以把错误处理也定义在数据流上集中在一段代码里。这个恰恰是传统异步嵌套写法很难做到干净的。1.3 适合谁读、先决条件这篇系列文章面向的读者大概有两类。第一类是写过几年 JavaScript、面对回调函数已经觉得肌肉酸痛的前端工程师。你已经熟悉 Promise 和 async/await但对“可取消的异步操作”“可组合的事件流”没有直观感受。第二类是刚开始接触 Angular 或其他响应式框架的开发者因为 Angular 里有大量 RxJS 的概念不理解 Observable 意味着你看很多官方文档都会是一脸懵。先说前提你最好已经了解Array.prototype.map、filter、reduce这些基本方法因为 RxJS 操作符的命名就是顺着这套习惯来的。如果你已经会使用Promise来处理异步那就更好了很多类比可以直接往 RxJS 上套。下面我们正式进入核心概念。2. 概念拆解Observable、Observer、Subscription 与 Scheduler第一次接触 RxJS 的人通常会被一堆术语劝退Observable、Observer、Subject、BehaviorSubject、Subscription、Operators、Scheduler、Multicast……但实际上最核心的就四样Observable、Observer、Subscription、Operators。Scheduler 可以先放一放。这节我会用生活化类比把每个概念讲透。2.1 Observable惰性执行的数据源用一句话概括Observable 是一个“函数”它接收 Observer 作为参数并在未来某个时间点把数据逐个发射给对方。它本质上是惰性的只有调用subscribe()后数据源才会真正开始工作。可以把它类比成“订阅一份报纸”。报纸社不会因为你订了报就马上把十年份的报纸全堆在你门口而是从订阅那天起每天早上送一份新的。每一份报纸就是流里的一个数据。若你中途退订送报员就会停止上门。在功能上Observable 与 Promise 最大的区别在于Promise 只能发射一个结果或一个错误且无法取消Observable 可以发射 0 个、1 个、多个甚至无限个数据而且可以用 Subscription 取消。这也是为什么在处理事件流、WebSocket 推送、定时器等场景时Observable 比 Promise 更合适。从代码层面看创建一个 Observable 的方式特别简单import { Observable } from rxjs; const number$ new Observable(subscriber { subscriber.next(1); subscriber.next(2); subscriber.next(3); subscriber.complete(); });这里的$后缀不是必须的但很多 RxJS 开发者习惯用它来标识这是一个流对象看到$就知道要subscribe省得和普通数组变量搞混。2.2 Observer怎么消费数据Observer 是“看报纸的人”。在 RxJS 中Observer 就是一个包含三个可选方法的对象next(value)流里吐出一个数据时触发error(err)流里发生错误时触发complete()流正常结束时触发。看一个最简单、最直白的订阅过程number$.subscribe({ next: value console.log(收到数据:, value), error: err console.error(出错了:, err), complete: () console.log(流结束) });运行后控制台会依次输出“收到数据: 1”“收到数据: 2”“收到数据: 3”最后输出“流结束”。这里的订阅动作会立即同步执行因为我们在创建 Observable 时是同步next的。但真实项目中绝大多数情况是异步的比如setTimeout包裹的发射、DOM 事件的响应这时控制台输出的时间就会推迟。还有一个细节Observer 的三个方法都可以省略。你可以只传一个回调函数它会默认被当成next。比如number$.subscribe(value console.log(value));这种写法用于“只关心数据、不关心错误和完成”的场景。但如果你真的在处理一个可能出错的流我强烈建议至少把error回调补上否则报错会被静默吞掉排起错来非常难受。2.3 Subscription 与取消执行Subscription 代表“这次订阅关系的凭证”。就像报纸订阅过程中你有权随时取消。在 RxJS 里的取消方式是调用.unsubscribe()。很多人学 RxJS 时容易忽略取消这一步其实在实际前端项目中取消订阅非常关键。举个场景如果你在组件的useEffect里订阅了一个流但组件销毁时没有取消订阅那流里的下一次数据仍然会触发回调如果你在回调里更新 DOM 状态或调用setState就会触发“在已卸载组件上更新状态”的警告甚至造成内存泄漏。正确的姿势是在合适的生命周期里取消订阅const subscription number$.subscribe(value console.log(value)); // 假设在 React 的 useEffect 清理函数中 subscription.unsubscribe();现在流行用takeUntil操作符来自动管理取消时机这在后面实战里我会专门演示。2.4 Scheduler 是干嘛的Scheduler 是 RxJS 里用来控制“任务何时执行”的调度器简单理解就是告诉流“用哪种时间维度来跑”。这不是系列第一篇的重点但你至少要知道有这个东西存在。比如默认情况下Observable的数据是同步发射的。如果某个 Observable 使用asyncScheduler调度它的发射就会被放进宏任务队列有点类似于setTimeout的效果。Angular 响应式编程的很多复杂调度都和 Scheduler 相关但初学者刚开始完全不需要碰它你只需要知道 RxJS 里的异步能力并不只靠浏览器 API而是设计了统一的调度抽象后续系列写到并发控制时我会展开。3. 环境准备与第一个实操示例光讲概念不留作业等于耍流氓。这一节我会带你搭建一个最简的 RxJS 环境然后写三个能直接运行的示例让你对 Observable 的操作有肌肉记忆。3.1 引入 RxJS 的方式最简单的方式是用 Vite 建一个纯前端项目然后安装 RxJSnpm create vitelatest rxjs-demo -- --template vanilla cd rxjs-demo npm install rxjs装完后在main.js里引入import { Observable } from rxjs;如果你不用打包器也可以用 CDN 直接在 HTML 里引入 RxJS 的全局版本脚本标签里的全局对象是rxjs比如rxjs.Observable。不过我个人建议还是用 npm Vite 的方式因为后续要写组合操作符模块化写法更清晰。3.2 创建 Observable 的几种方式除了手动new ObservableRxJS 提供了很多工厂函数日常开发里用的频率比new Observable高得多。下面列几个最常见的import { of, from, fromEvent, interval } from rxjs; // of: 把若干普通值转成流 of(1, 2, 3).subscribe(console.log); // from: 把数组、Promise、类数组转成流 from([10, 20, 30]).subscribe(console.log); from(fetch(/api/users)).subscribe(console.log); // interval: 每隔指定毫秒发射一个自增数字 interval(1000).subscribe(console.log);of适合把一组静态数据包装成 Observablefrom适合把已有的 Promise 或数组快速转成流interval则用来做定时器轮询。还有fromEvent它在 DOM 事件处理里尤其有用值得单独演示。3.3 从事件到 Observable 的实战现在写一个稍微贴近真实需求的例子监听输入框事件并把输入内容打印出来。input idsearch typetext placeholder输入关键词 /import { fromEvent } from rxjs; const input document.querySelector(#search); const input$ fromEvent(input, input); input$.subscribe(event { console.log(用户输入:, event.target.value); });这段代码看起来和直接addEventListener差不多但input$这个流对象是可以被保存、传递、组合的。比如我想让输入事件“防抖 300 毫秒后再触发”就不需要自己写setTimeout清理逻辑直接在流上加一个debounceTime(300)操作符就行下一节马上演示。写到这里你会发现一个规律RxJS 的核心操作不是“监听”而是“加工”。真正的监听发生在subscribe那一步而前面的各种操作符都在对数据流做修饰和变换。这个心智模型一旦建立后面看复杂的响应式代码就会轻松得多。4. 常用操作符拆解与组合实战操作符是 RxJS 的灵魂。学操作符最忌讳死记硬背我的建议是先掌握最常用的几个明白它们每个解决什么问题然后从实际需求反推用什么操作符。4.1 map、filter、tap这三个操作符和 JavaScript 数组方法同名用法也几乎一样正因为如此才容易上手。map用于对每个数据做变换const doubled$ of(1, 2, 3).pipe( map(value value * 2) ); doubled$.subscribe(console.log); // 输出 2, 4, 6filter用于筛选数据const even$ of(1, 2, 3, 4).pipe( filter(value value % 2 0) ); even$.subscribe(console.log); // 输出 2, 4tap的作用就特殊一点它不改变数据本身而是让你在流的中间位置做“查看”或“副作用”比如打日志、更新某些外部状态。可以把它理解为一条传送带旁边装了块玻璃你可以看清经过的包裹长什么样但别伸手去改它。of(a, b).pipe( tap(value console.log(经过tap:, value)), map(value value.toUpperCase()), tap(value console.log(经过map后:, value)) ).subscribe();有一点必须提醒不要在map或filter里做副作用操作比如修改外部变量、调用 API。设计上操作符应当保持“纯函数”特性这样才容易组合和测试。副作用操作要放进subscribe或tap里这是一个不可忽视的纪律。4.2 debounceTime、distinctUntilChanged、switchMap这三个操作符配合在一起就是“搜索框防抖 忽略重复值 请求竞态处理”的黄金组合也是真实项目里最高频的组合之一。我直接给一个完整示例基于上一节的输入框import { fromEvent, of } from rxjs; import { debounceTime, distinctUntilChanged, map, switchMap, catchError } from rxjs/operators; const input document.querySelector(#search); const input$ fromEvent(input, input); const search$ input$.pipe( map(event event.target.value.trim()), debounceTime(300), distinctUntilChanged(), switchMap(query { // 假设这是一个返回 Promise 的请求函数 return mockSearch(query).pipe( catchError(err of({ error: err.message })) ); }) ); search$.subscribe(result { console.log(搜索结果:, result); });逐个解释map把事件对象转成输入框的值debounceTime(300)用户停止输入 300 毫秒后才继续往下传数据。如果用户一直快速输入就会不断重置计时器真正做到“等人打完了才查”。这比自己手写setTimeout加清理逻辑要直观太多distinctUntilChanged()只允许“和上一次不同的值”通过。比如用户输入 “abc”过一会儿又删掉重新输入 “abc”这种场景下第二次结果不会触发请求switchMap核心作用在于切换内部流。它会把前一个内部订阅取消掉然后订阅新的内部流。放在搜索场景里就是请求 A 还在飞行用户又输入了新关键词那么请求 A 会被自动取消只保留最新请求 B 的结果。旧请求后返回也不会覆盖新结果这正好解决了我在开头提到的异步竞态问题。switchMap背后有个“取消旧流”的机制这也是 Observable 相对 Promise 最有战斗力的一点。记住Promise 存在竞态但switchMap能从根源上规避竞态。4.3 combineLatest、forkJoin 的差别除了顺序型操作符流组合操作符也是日常必需品。combineLatest和forkJoin都用于把多个流合到一起但语义完全不同。forkJoin类似Promise.all等待所有流都完成然后一次性把每个流的最终值打包成一个数组发射。它适合“并行请求多个互不依赖的接口都成功后一起处理”的场景。import { forkJoin, of } from rxjs; import { delay } from rxjs/operators; forkJoin({ users: of([{ id: 1 }]).pipe(delay(1000)), posts: of([{ id: 1 }]).pipe(delay(2000)) }).subscribe(result { console.log(所有请求完成:, result); });这段代码 2 秒后会输出包含users和posts两把键的对象注意forkJoin只会在所有内部流都complete时发射结果。combineLatest则是每当任一数据源发射新值时就把各个数据源的最新值组合在一起发射。它不会等待流结束因此非常适合“多个联动筛选器”的场景。import { combineLatest, fromEvent } from rxjs; const category$ fromEvent(categorySelect, change); const keyword$ fromEvent(keywordInput, input); combineLatest([category$, keyword$]).subscribe(([cEvent, kEvent]) { console.log(当前分类:, cEvent.target.value); console.log(当前关键词:, kEvent.target.value); });每次分类变化或每次关键词变化你都会拿到两个控件的当前值天然适合做联动查询。真实项目里我通常会再用debounceTime、distinctUntilChanged去控制请求频率并配合switchMap处理竞态。5. 常见问题与排查技巧实录理论看多了容易飘实操踩坑才会长记性。这一节我分享一下实际使用 JavaScript 反应式编程时最常遇到的问题和排查思路内含不少我走过的弯路。5.1 Observable 没有输出先查订阅新手最容易踩的第一个坑定义了 Observable也调用了操作符但控制台什么也没有。原因通常很简单——没有调用subscribe()。前面说过 Observable 是惰性的你无论在上面接多少.pipe操作符只要不订阅数据源就永远不会启动。有些开发者会把map、filter相当于数组方法来用以为调用pipe就会执行这完全是误解。排查方法先在源头加一个tap打印日志确认有没有数据进入操作符链路。如果源头有事件但链路上没有说明操作符出了问题如果源头没有事件说明事件绑定或 Observable 创建有问题。5.2 事件重复触发第二个高频坑重复订阅。在 Angular 或 React 里如果组件被多次初始化而你的订阅代码在初始化阶段执行且没有在清理阶段取消订阅就会出现“同一次输入回调执行两次以上”的现象。我见过的一个典型场景React 组件的useEffect里订阅了fromEvent但依赖数组传了空数组按理说应该只订阅一次某个版本改动后组件被套了一层React.StrictMode开发环境下 effect 会执行两次订阅也重复了。修复方式是使用takeUntil或Subscription.add来集中管理import { Subject } from rxjs; import { takeUntil } from rxjs/operators; const destroy$ new Subject(); input$.pipe(takeUntil(destroy$)).subscribe(console.log); // 组件卸载时 destroy$.next(); destroy$.complete();destroy$是一个特殊主题当它发射值时takeUntil会立刻让上游流停止。这种方式把“取消订阅”的逻辑统一放到一个信号源里清掉比每次手动调unsubscribe()省心也方便在多个订阅之间复用。5.3 用 BehaviorSubject 解决状态同步问题有时候你需要一个既能订阅、又能手动改值的“状态容器”。RxJS 的Subject就是双向通道可以调用next往下游推送数据也可以让下游订阅。但普通 Subject 有个特点订阅者只能收到它订阅之后的数据。如果组件在状态已经更新后才订阅就会错过当前值拿不到最新状态。这时就要用BehaviorSubject。它保存了“当前的最新值”新订阅者进来后会立即收到这个值。这一点和前端状态管理里的“初始化状态”很像。import { BehaviorSubject } from rxjs; const currentUser$ new BehaviorSubject(null); // 登录成功后更新 currentUser$.next({ id: 1, name: 张三 }); // 新组件订阅时会立即拿到当前值 currentUser$.subscribe(user { console.log(当前用户:, user); });即使这个订阅行为发生在next之后回调也能立刻执行打印出{ id: 1, name: 张三 }。如果你用普通 Subject就可能什么都拿不到。在很多中后台系统里我会用 BehaviorSubject 做“应用级状态中心”配合distinctUntilChanged控制不同模块的状态更新频率。5.4 热/冷 Observable 惹的祸“冷 Observable”是每个订阅者都得到一套独立的数据流“热 Observable”是所有订阅者共享同一个数据源。DOM 事件通过fromEvent创建出来的就是热流因为不管有没有订阅者用户点击事件本身都会发生而直接用new Observable包一层定时器通常属于冷流。这不只是一个理论区分它会影响你的内存和状态。曾经有个项目里我用了某个冷流封装轮询请求每个组件订阅都会触发自己的定时器导致多个组件同时轮询同一个接口流量激增。后来改成了shareReplay将冷流变成共享流这个问题才解决。关于热冷流的深入分析包括share、shareReplay、multicast这些操作符我会放到本系列的第二篇详细讲解。这里你只需要记住一个排查原则如果同一个 Observable 被多处订阅后行为异常优先怀疑它是多个独立实例在各自运行而不是共享同一份数据。6. 从实操角度聊聊我对反应式编程的学习心得这一节不算正式教程更像是个人经验沉淀。我见过太多人学了 RxJS 两三天就说“操作符太多了记不住”然后放弃。我的真实体会是一开始别追求学完所有操作符而是先建立一个“流”的直觉。我自己是从这三个场景练出感觉的搜索框防抖练debounceTime、distinctUntilChanged、switchMap多接口并行请求练forkJoin、combineLatest、catchError组件状态同步练BehaviorSubject、shareReplay、takeUntil。每个场景都要手写至少一遍然后尝试反过来问自己如果不用响应式编程这个功能我要写多少状态变量、多少清理逻辑这么一比你才能体会为什么在生产项目里值得引入 RxJS。另一个心得是调试响应式代码时不要只盯控制台。在数据流的关键节点插入tap(console.log)是好办法但项目大了以后日志会非常杂乱。我习惯给每个流起一个清晰的后缀名例如searchInput$、searchResult$、selectedCategory$这样日志里能明显分辨出数据流向。再配合浏览器的扩展调试工具可以把当前订阅关系、发射值、时间线都可视化出来排查效率会高很多。关于后续扩展这里先埋个伏笔本系列第二篇会专门讲 Subject 家族Subject、BehaviorSubject、ReplaySubject、AsyncSubject之间的区别以及如何用shareReplay做出可靠的缓存流第三篇会结合 React 实战用useObservable这样的轻量封装把响应式编程真正落地到组件里。如果你现在已经有项目在手建议先照着这篇里的搜索防抖例子玩一遍哪怕只是写个本地 demo也比你读十遍文档有用得多。我自己在刚开始接触 JavaScript 反应式编程的时候也曾经被各种术语绕晕过但后来发现只要抓住“数据流 订阅 操作符”这条主线绝大部分概念都能顺着这根线理解清楚。最后再分享一个小技巧当你觉得一个场景用 RxJS 写得很绕时先停下来思考一下——我是不是在“用命令式的脑子写响应式的代码”如果答案是肯定的就回到数据流本身问自己三个问题数据从哪里来每一步要做什么转换谁最终需要消费这些数据想明白这三件事90% 的代码结构都会自然浮现出来。

相关新闻

ChatGPT、Codex工程方法:多个Agent同时开PR,为什么每个PR都正确,合并以后却可能出错?

ChatGPT、Codex工程方法:多个Agent同时开PR,为什么每个PR都正确,合并以后却可能出错?

最近用 ChatGPT、Codex 同时推进多个开发任务时,我越来越明显地遇到一个新问题:单个PR没问题,不代表多个PR合在一起以后也没问题。比如一个大型项目里,同时开了三个Agent任务。Agent A负责改鉴权逻辑。Agent B负责调整缓存。Agent…

2026/10/11 5:36:47 阅读更多 →
agent-skills 实战:从单体提示词到可插拔技能单元

agent-skills 实战:从单体提示词到可插拔技能单元

1. 从零理解 agent-skills:它到底是什么,能解决什么问题第一次看到 agent-skills 这个词,很多人会以为是某个具体框架的名字,其实它更像是一类工程实践的统称——把智能体(Agent)需要具备的能力拆成一个个可…

2026/10/11 5:35:47 阅读更多 →
opencode v2升级避坑指南:配置迁移与权限模型全解析

opencode v2升级避坑指南:配置迁移与权限模型全解析

我用 opencode 也断断续续用了大半年,v1 时代一直挺顺手,所以 v2 一发布,我几乎是第一时间就升了。结果那个晚上基本都花在跟配置文件和报错较劲上,前前后后折腾了快一天,才把原来那套工作流完整搬过来。在这个过程里我…

2026/10/11 5:35:47 阅读更多 →

最新新闻

Cursor 高级指南(七):CLI 安装、非交互、Worktree 与 ACP 实战配置

Cursor 高级指南(七):CLI 安装、非交互、Worktree 与 ACP 实战配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 7:05:37 阅读更多 →
Unity 笔记二:数字孪生智慧城市中 LookAt 与 Cursor 的协同配置到 TaoToken

Unity 笔记二:数字孪生智慧城市中 LookAt 与 Cursor 的协同配置到 TaoToken

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 7:05:37 阅读更多 →
Zion 接入 Gemini 3.5 flash 后,AI Agent Builder 的 BYOM 配置怎么改到 TaoToken

Zion 接入 Gemini 3.5 flash 后,AI Agent Builder 的 BYOM 配置怎么改到 TaoToken

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 7:05:37 阅读更多 →
2026告别漫长等待:百度网盘冷门资源类似pandownload加速法

2026告别漫长等待:百度网盘冷门资源类似pandownload加速法

很多人在日常保存或者获取资料的时候,经常会遇到文件传输进度停滞不前的情况。面对几十兆甚至几个小容量的文件,进度条却像蜗牛爬行一样缓慢,确实很容易让人感到焦躁和无奈。 其实在很多时候,下载速度提不上来不一定是因为外界的…

2026/10/11 7:05:36 阅读更多 →
OWASP 五大 AI 安全框架:从对话、Agent、技能到协议的全链路防护体系

OWASP 五大 AI 安全框架:从对话、Agent、技能到协议的全链路防护体系

随着生成式AI、自主智能体(Agent)、插件技能生态的大规模落地,AI安全风险早已不再局限于“模型幻觉、提示注入”等基础问题。从模型对话输出、智能体自主决策,到第三方技能插件执行、内外系统协议交互,每一层链路都存在…

2026/10/11 7:05:36 阅读更多 →
安卓分屏自动左滑脚本:Auto.js+ADB实现3秒滑动挂机

安卓分屏自动左滑脚本:Auto.js+ADB实现3秒滑动挂机

先说个真实场景:我手机上装了某短视频极速版,每天要做签到和刷视频任务,手得一遍遍地左滑,滑到拇指发酸。后来我寻思,这滑动动作完全可以用脚本代替。于是就有了标题里这个功能——“循环3秒左滑-支持屏幕上下分屏”。…

2026/10/11 7:04:36 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 5:23:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 10:38:42 阅读更多 →