react-hooks-async:自定义Hooks解决异步请求取消与组合

简介:react-hooks-async 是一套面向 React 开发者的自定义 Hooks 工具库,解决原生 Promise 无法中止/取消的痛点。它基于 AbortController 将可终止能力封装进 Hooks 中,并提供 useAsyncTask、useAsyncRun、useAsyncCombineAll/Race/Seq 等现成钩子,适用于请求竞态、条件执行、进度跟踪等场景。包内共有 92 个文件,以 js/tsx 源码为主,搭配 ts 类型定义、json 配置、html 示例与快照测试,整体仅 295KB,轻量易集成。已有 315 人学习下载。包内整理好了 core 钩子、axios/fetch/delay/timeout 等任务封装、TypeScript 声明、多场景示例(含分页、类型搜索、Wasm 调用)以及测试用例,方便前端开发者快速上手、按需扩展或移植到既有项目。

1. react-hooks-async:把异步请求的取消与组合收进自定义 Hook

react-hooks-async 这套自定义 Hook,核心就两句话:让异步函数在组件卸载时能自动终止,让多个异步任务能被按需组合编排。做中后台前端的人几乎每天都被这类问题绊住——列表页切走再切回来,旧请求把新响应覆盖了;搜索框输入还没停,请求已经提前发出去了;一个页面三个下拉框的依赖接口互相等待。这套库把 AbortController 和 React Hooks 的生命周期绑在一起,用 useAsyncTask、useAsyncRun 以及 useAsyncCombineAll / Seq / Race 几个 Hook 把上述场景收敛成几十行代码。适合在 React 16.8+ 项目里替换手写的请求状态机,尤其适合接口多、切页频繁、带搜索联动的管理端页面。

2. 为什么需要 react-hooks-async:useEffect 里裸写 async 的三个死结

2.1 竞态条件:先发的请求不一定是先回的

在说这套库怎么用之前,得先讲清楚它到底在处理 useEffect 里的哪些老毛病。最常见的是竞态条件:用户在搜索框里输入 "react",请求 A 发出去了,继续输入 "react hooks" 又发出请求 B。网络不稳定时,B 可能先返回,A 可能慢悠悠最后才落地。如果代码只是简单地把 response 写入 state,那最后写进去的很可能反而是 A 的旧数据,界面就显示了过期结果。

这类 bug 非常难 Debug,因为本地几乎复现不出来,用户网络一慢就随机出现。我最早是给每次请求编一个递增序号,响应回来先比对序号再决定要不要 setState,每个异步请求都写一遍这套逻辑,代码很快就臭了。react-hooks-async 的做法是:每次任务启动时归库内部持有当前的 AbortController,下一次启动或组件卸载时先把上一个 abort 掉。abort 之后,旧 Promise 即使 resolve 了,状态也不会再被写进组件,竞态从源头被掐断。

这里有个关键点要提前说清楚:这套库能防竞态,前提是你的异步函数确实消费了 signal。如果 async 函数里压根没把 signal 传给请求层,abort 就只是个空动作,后面避坑章节会专门展开。

2.2 AbortController 的两种消费方式与 React 的衔接

AbortController 是浏览器原生的取消机制,本身和 React 没有半点关系。它主要由两部分组成:controller.abort() 方法负责触发取消,controller.signal 负责被传递和监听。fetch 原生支持 signal 选项;axios 从 0.22 开始也支持 config.signal;自定义的异步任务则要靠 signal.addEventListener('abort', ...) 手动收尾。

很多新手对 abort 有一个认知偏差,以为调了 abort() 网络请求就会立刻断开。实际上 abort 只是把一个事件广播出去,真正断开连接的是 fetch 或者 axios 内部对 signal 的监听逻辑。也就是说,如果你的异步函数没有把 signal 透传给底层请求库,abort 就是空放一枪。react-hooks-async 的做法是,把 signal 作为参数注入到你的异步函数签名末尾,你只需要在写请求时把它传给 fetch 或者 axios 的 signal 选项。controller 的生命周期它来管,组件卸载它自动 abort,你只负责"用起来"。

2.3 把异步状态收敛成 pending / result / error 三个字段

裸写 useEffect 的第三个痛点是状态字段膨胀。一个请求往往需要 loading、data、error 三个 useState,页面同时挂着五个请求就是十五个 useState,中间还夹着 setLoading(true) 忘还原、catch 之后 setError 忘置 null 这类手滑。状态一多,组合判断就变得很玄学,比如"loading 和 error 同时为 true 时界面渲染哪个分支"这种问题,代码评审时谁也说不清。

react-hooks-async 收敛了这个问题:一个任务对象里固定有 pending、error、result 三个字段,任务没启动、启动中、成功、失败,全部从同一个返回值里读。加载分支、错误分支、成功分支各取所需。后面我会把每个字段的取值时机拆开讲,这里先记住一个判断标准:页面里出现三个以上手写 loading / data / error 组合,并且这些状态互相之间有联动关系时,就值得用这套东西做一次收敛。

3. useAsyncTask 落地上手:最小示例与参数拆解

3.1 安装与最小完整示例

安装只需要一条命令,然后就可以在组件里直接用:

npm install react-hooks-async

下面是一个拉取用户列表的最小示例,覆盖了这套库最基础的用法:

import { useAsyncTask, useAsyncRun } from 'react-hooks-async'; const fetchUserList = async ({ signal }) => { const response = await fetch('/api/users', { signal }); if (!response.ok) { throw new Error(`HTTP ${response.status}`); } return response.json(); }; const UserList = () => { const task = useAsyncTask(fetchUserList, []); useAsyncRun(task); if (task.pending) return <div>加载中...</div>; if (task.error) return <div>加载失败:{task.error.message}</div>; return ( <ul> {task.result.map((user) => ( <li key={user.id}>{user.name}</li> ))} </ul> ); };

这段代码的逻辑是:useAsyncTask 接收一个异步函数和一个依赖数组,生成一个可被启动的任务对象,useAsyncRun 在组件挂载时启动它。重点看第 4 行,异步函数签名里解构出了 signal,fetch 的第二个参数把它传给底层请求,这就是取消信号生效的链路。组件卸载时库会自动调 abort(),这次请求不会再有回调落地到已卸载的组件上。

依赖数组在这里的作用和 useEffect 的 deps 完全一致:依赖项变化时任务对象被重建,useAsyncRun 会用新任务重新发请求。比如把 [] 换成 [userId],userId 一变立即重新拉数据,同时上一次请求会被 abort。这个行为后面避坑章节会重点讲,先记住"依赖数组变化会带来任务重启和旧请求终止"。

3.2 参数与返回值逐个拆解

useAsyncTask 的完整签名是 useAsyncTask(asyncFunc, deps)。asyncFunc 是你写的业务异步函数,它的前几个参数是业务入参,最后一个参数固定是包含 signal 的对象。deps 数组决定任务何时被视为"新任务",引用一旦变化,旧任务弃用,对应请求被 abort。

useAsyncRun 的签名是 useAsyncRun(task, ...args),...args 会原样透传给 asyncFunc。比如要传一个 teamId:

const fetchUserListByTeam = async (teamId, { signal }) => { const response = await fetch(`/api/teams/${teamId}/users`, { signal }); return response.json(); }; const TeamUsers = ({ teamId }) => { const task = useAsyncTask(fetchUserListByTeam, [teamId]); useAsyncRun(task, teamId); // task.pending / task.error / task.result 与上例相同 };

此时 fetchUserListByTeam 的定义要写成 async (teamId, { signal }) 的形式,teamId 是业务参数,{ signal } 是库里注入的取消信号。返回的 task 对象中,pending 在启动前为 false,任务 resolve 或 reject 后回到 false;result 在成功后写入数据;error 在失败后写入错误对象。注意 result 和 error 不会同时有值,成功时 error 保持之前的默认值,失败时 result 保持 undefined,判断分支时不需要额外清理。

提示:如果团队内已经有统一封装的 request 函数,记得在封装层暴露 signal 透传参数,否则异步函数里拿到 signal 也递不到真正发请求的那一层。

3.3 触发时机:挂载启动与事件启动要分开选 API

useAsyncRun 属于"组件挂载就请求"的被动模式,只会在挂载和 deps 变化时启动。还有一类场景是点击按钮才请求,比如提交表单、加载更多,这类场景用 useAsyncRun 就不合适了,它没有暴露手动启动的入口。对应的事件型 API 是 useAsyncFunction:

import { useAsyncFunction } from 'react-hooks-async'; const submitForm = async (formData, { signal }) => { const response = await fetch('/api/submit', { method: 'POST', body: JSON.stringify(formData), signal, }); return response.json(); }; const Form = () => { const submit = useAsyncFunction(submitForm); const onClick = () => { submit({ name: '张三', level: 3 }); }; return ( <button onClick={onClick} disabled={submit.pending}> {submit.pending ? '提交中...' : '提交'} </button> ); };

useAsyncFunction 返回的是一个可随时调用的函数,返回值同样挂着 pending、error、result 字段,所以提交按钮的 loading 和禁用状态可以直接读 submit.pending。它内部同样维护专属的 AbortController,组件卸载时自动 abort;用户连续点击提交时,上一次请求也会被 abort,避免旧响应覆盖新响应。到这里,挂载场景和事件场景都有了对应的 API,下一步就是看多个任务怎么编排。

4. 组合能力:useAsyncCombineAll / Seq / Race 怎么选

4.1 三种组合器的行为差异与选型依据

单个任务的收放已经能跑通,真正的价值在页面级编排。react-hooks-async 里最有特色的就是三个组合器:useAsyncCombineAll、useAsyncCombineSeq、useAsyncCombineRace。

组合器并发模式完成条件失败行为典型场景
All并行全部成功才算成功任一失败整体进 error,其余任务被 abort页面初始化拉取多个互不依赖的接口
Seq串行最后一个任务成功才算成功中途失败整体进 error,后续任务不再启动先拿 token 再拉详情数据
Race并行第一个完成即定胜负先 reject 则整体 error,先 resolve 则整体 result请求超时兜底、主备接口竞速

三个组合器都接收一组 task 对象,返回一个组合后的 task,这个组合 task 同样具备 pending、error、result 字段,可以继续传给 useAsyncRun 或者再嵌套组合。选型判断看接口关系就行:互不依赖用 All;强依赖顺序用 Seq;需要抢时间用 Race。实际页面里 All 和 Race 最多,Seq 只在 token 链路上比较常见。

4.2 并行请求与串行请求的落地写法

并行请求的写法是把两个独立任务交给 useAsyncCombineAll,再统一启动:

import { useAsyncTask, useAsyncRun, useAsyncCombineAll, } from 'react-hooks-async'; const fetchProfile = async ({ signal }) => (await fetch('/api/profile', { signal })).json(); const fetchOrders = async ({ signal }) => (await fetch('/api/orders', { signal })).json(); const Dashboard = () => { const profileTask = useAsyncTask(fetchProfile, []); const ordersTask = useAsyncTask(fetchOrders, []); const combined = useAsyncCombineAll(profileTask, ordersTask); useAsyncRun(combined); if (combined.pending) return <div>加载中...</div>; if (combined.error) return <div>加载失败:{combined.error.message}</div>; return ( <div> <p>昵称:{profileTask.result.name}</p> <p>订单数:{ordersTask.result.length}</p> </div> ); };

useAsyncCombineAll 不负责启动任务,只负责把两个任务的状态合并成一个状态源。useAsyncRun(combined) 会让库同时启动 profileTask 和 ordersTask 对应的异步函数。errror 分支的判断要理解语义:All 模式下任意一个任务 reject,combined.error 就有值,但另一个请求此刻可能还在飞。进入错误渲染分支时,库内部其实已经对未完成的那个任务执行了 abort,所以不会留下泄漏的请求回调。

串行场景换成 useAsyncCombineSeq(taskA, taskB),taskB 对应的异步函数会在 taskA 成功后自动收到上一个任务的返回值作为参数。类似"先调登录接口拿 token,再用 token 调详情接口"这种链路,Seq 比在前一个 async 函数里手动 await 后一个请求要清晰,因为每个环节的 abort 信号独立管理,中途失败不会残留后续请求。

4.3 和 Suspense / render-as-you-fetch 的边界

React 生态里还有一条数据请求路线是基于 Suspense 的 render-as-you-fetch,强调在渲染之前就发起请求,组件切过去时数据已经在路上。react-hooks-async 走的是 hooks 编排路线,组件挂载后才发起请求,适合数据不敏感、组件按需加载的管理端页面。两者定位不同:Suspense 解决"数据预取与渲染时序",这套库解决"请求的取消与组合"。

它们可以配合使用,外层用 React.lazy 加 Suspense 控制代码分包,内层用 react-hooks-async 管数据请求的取消与编排。但我个人的习惯是一个项目只保留一套请求状态方案,要么全部走 Suspense 风格,要么全部走 hooks 编排,混用会让团队里新人很难判断一个请求到底归谁管,出问题时的排查路径会多出一整条。

5. 避坑手册:终止失效、卸载警告与重复触发

5.1 现象:组件卸载后控制台刷 "state update on unmounted component" 警告

这个警告在写异步组件的项目里几乎人人见过。原因是请求的 Promise 在组件卸载之后才 resolve,回调里的 setState 落在一个已经不存在的组件上。react-hooks-async 本意是自动终止来避免这个问题,但如果你用的是 useAsyncFunction 手动触发,或者异步函数体内没有消费 signal,卸载后照样会刷这套警告。

原因:库内部依赖 signal 的 abort 事件来阻止后续 setState,signal 没被消费就等于这道保护没生效。解决:一是确认异步函数签名的对象参数里有 signal 并把它传给了请求层;二是不要在组件卸载后继续调用手动触发函数,事件回调里加一层 mounted 标记做防御更稳妥。

5.2 现象:调了 abort() 但请求照样完成

这是整套方案里最常见的翻车点。原因很直接:abort() 只是广播了一个事件,你的 fetch 或 axios 实例没有监听这个信号。很多人把 signal 写在函数签名里,但业务代码里用的还是封装好的 request 函数,封装层根本没暴露 signal 透传参数,信号在这一层就丢了。

解决:把 signal 一路透传到底——fetch 的第二个参数、axios 的 config.signal、或者你自己封装层的 options 对象。如果是自己写的 Promise,要给 signal 注册 'abort' 事件监听,在回调里把 Promise reject 掉。这一步做到位,react-hooks-async 的终止能力才真正成立,否则它和普通封装库没有区别。

5.3 现象:依赖数组一动任务就重复执行,旧请求还在飞

useAsyncTask 的 deps 数组和 useEffect 的依赖数组行为一致,依赖引用变化就意味着新任务。很多人把不稳定的值写进 deps,比如每次渲染都新建的内联函数或者对象字面量,结果任务反复重建、请求连环发,页面上同时飞着三四个重复请求。

原因:deps 里放的是派生值或字面量,每次渲染引用都不同,任务对象必然重建。解决:deps 只放原始值或 useMemo 过的稳定引用;确实要传复杂对象就把它拆成基本类型字段。另外,deps 变化后旧任务被 abort 是预期行为,不是 bug。如果你发现旧请求没被终止,回到 5.2 检查 signal 透传。

5.4 现象:combineAll 里一个接口失败,整页停在 error 分支

严格说这是语义理解问题而不是库的缺陷。All 的语义就是全部成功才算成功,一个失败整体进 error,页面只能渲染错误分支。问题在于开发阶段很容易把 All 误当成"互不干扰的并行",结果一个本可降级的可选接口断了,整页跟着崩。

原因:对组合器语义理解偏差。解决:如果某个接口失败不应该拖垮整页,把它拆出去单独用 useAsyncTask 管,不要并入 All;或者在该接口的异步函数体内 catch 住异常,返回兜底值。Race 同理,它是拿来抢快的,不是拿来容错的,容错要在任务函数内部做,而不是在组合器层面做。

5.5 现象:浏览器报 AbortError,又被自己的 catch 吞掉

用 fetch 配合 signal 时,abort 触发后 fetch 的 Promise 会以一个 AbortError 被 reject。很多人习惯在异步函数里 catch 所有异常返回 null,于是一个正常的终止操作也被 catch 接住,error 状态被污染成"看起来像业务失败"。

原因:catch 语句没有区分 AbortError 和真正的业务异常。解决:在 catch 里判断错误对象的 name 是否为 'AbortError',是就直接 throw,让它作为终止信号继续往上传播;否才按业务错误处理。这是一个非常细节但影响判断正确性的点,遇到玄学 loading 问题先查这里。

6. 进阶:把 abort 信号接进 axios 与自定义超时编排

6.1 把 signal 传给 axios 与第三方 SDK

axios 从 0.22 起支持 config.signal,直接透传即可:

const fetchUserList = async ({ signal }) => { const response = await axios.get('/api/users', { signal }); return response.data; };

第三方 SDK 不一定认 signal,常见做法是包一层适配:监听 signal 的 'abort' 事件,在回调里调用 SDK 自带的 cancel 或 abort 方法。这套库本身不限制你怎么消费 signal,它只负责把信号的生命周期交给组件,signal 到了业务层怎么用是你自己的自由。

6.2 用 Race 实现超时兜底与定时器清零

竞赛模式最有价值的应用是超时控制,把真实请求和一个超时任务丢进 Race:

const timeoutTask = async ({ signal }) => new Promise((_, reject) => { const timer = setTimeout( () => reject(new Error('request timeout')), 2000 ); signal.addEventListener('abort', () => { clearTimeout(timer); reject(new DOMException('aborted', 'AbortError')); }); }); const combined = useAsyncCombineRace( useAsyncTask(fetchUserList, []), useAsyncTask(timeoutTask, []) ); useAsyncRun(combined);

这段逻辑是:2 秒内真实请求没返回,timeoutTask 先 reject,Race 整体进入 error 分支;反过来真实请求先返回,Race 进入 result 分支,同时库会 abort timeoutTask,触发监听器里的 clearTimeout。超时和取消共用同一条 abort 链路,定时器必然被清掉,不会出现定时器泄漏。从那以后,我每次新建异步请求组件都会强制走一遍三步自查:先确认异步函数接收了 signal,再确认 signal 透传到了底层请求调用,最后看一眼 deps 里有没有不稳定引用。这套习惯帮我挡掉了绝大多数线上才复现的脏数据问题。希望帮到你。

本文还有配套的精品资源,点击获取

相关新闻

AI MV制作全流程:DeepSeek+豆包+即梦+剪映实战指南

AI MV制作全流程:DeepSeek+豆包+即梦+剪映实战指南

简介&#xff1a;这份PDF资源面向希望入门AI音乐视频制作的创作者与爱好者&#xff0c;以于和伟演唱的《只字不提》MV为完整案例&#xff0c;串联DeepSeek、豆包、即梦与剪映四款工具&#xff0c;解决从歌词画面描述词生成、图像与视频素材产出到后期剪辑的全流程衔接问题。资源…

2026/10/20 12:38:25 阅读更多 →
PAPR如何偷走系统容量?从香农公式到OFDM工程实现的峰值信道比解析

PAPR如何偷走系统容量?从香农公式到OFDM工程实现的峰值信道比解析

信息论与编码这门课讲信道容量的时候&#xff0c;几乎所有人都在背香农公式&#xff1a;C B log2(1 SNR)。但很少有人会想&#xff0c;这个SNR用的是平均功率&#xff0c;还是峰值功率&#xff1f;峰值信道比&#xff08;PAPR&#xff09;这个看似不起眼的比值&#xff0c;就…

2026/10/20 12:38:25 阅读更多 →
appinfo.dll丢失?三种免费安全恢复方法,无需下载任何文件

appinfo.dll丢失?三种免费安全恢复方法,无需下载任何文件

前阵子帮人处理一台电脑&#xff0c;打开任何软件都弹窗提示“找不到appinfo.dll”&#xff0c;甚至桌面操作都卡顿。网上搜了一圈&#xff0c;清一色是各种“DLL免费下载”页面&#xff0c;看着就像在下载病毒。其实这个文件原本属于系统核心组件&#xff0c;只要用的方法正确…

2026/10/20 12:38:25 阅读更多 →

最新新闻

AF_XDP 实战指南:Ubuntu 24.04 上基于 eBPF 的高性能包处理

AF_XDP 实战指南:Ubuntu 24.04 上基于 eBPF 的高性能包处理

1. 项目概述&#xff1a;AF_XDP 到底解决什么问题碰上 AF_XDP 这个技术点的人&#xff0c;多半是已经在 Linux 上做高性能包处理&#xff0c;或者被 DPDK 的运维成本折腾过之后&#xff0c;想在内核生态里找个折中方案。AF_XDP 不是一个框架&#xff0c;而是 Linux 内核提供的地…

2026/10/20 23:41:33 阅读更多 →
用Unity打造桌面精灵:透明窗口、鼠标穿透与动画实战

用Unity打造桌面精灵:透明窗口、鼠标穿透与动画实战

简介&#xff1a;这是一份基于Unity引擎开发桌面精灵的完整工程资源&#xff0c;面向希望实现类似QQ宠物透明浮动桌面形象的Unity开发者。资源围绕窗口无边界设置、透明材质渲染、UI布局、Animator动画控制以及鼠标交互事件等关键技术点组织&#xff0c;适合有一定Unity基础、想…

2026/10/20 23:41:33 阅读更多 →
GLSL变量与类型系统详解:从标量到矩阵的Shader避坑指南

GLSL变量与类型系统详解:从标量到矩阵的Shader避坑指南

如果你写过一段时间的着色器&#xff0c;大概率遇到过这种时刻&#xff1a;shader编译失败&#xff0c;错误信息指向某个变量&#xff0c;你盯着那一行看了很久&#xff0c;愣是没发现哪里有问题。我印象最深的一次是在某个延迟渲染demo里&#xff0c;片元着色器把法线数据当成…

2026/10/20 23:41:33 阅读更多 →
C语言是什么?从底层原理到上手路径的全面解析

C语言是什么?从底层原理到上手路径的全面解析

编程这行干久了&#xff0c;总会被外行朋友或刚入行的新人问到同一个问题&#xff1a;“C语言到底是什么&#xff1f;” 每次被问到&#xff0c;我都会愣一下&#xff0c;因为这个问题看似简单&#xff0c;真要一两句话说清楚还挺难。它不像Java能“写安卓APP”&#xff0c;也不…

2026/10/20 23:41:33 阅读更多 →
好写作AI如何用游戏化设计破解写作恐惧,养成写作习惯

好写作AI如何用游戏化设计破解写作恐惧,养成写作习惯

1. 好写作AI到底在做什么&#xff1a;把“写作”变成“练级”1.1 它解决了什么问题&#xff1a;写作恐惧不是懒&#xff0c;是“防御”我见过太多人说自己“不会写”“写不出来”&#xff0c;包括我自己也曾是这样。面对一个空白文档&#xff0c;光标一开一合&#xff0c;脑子里…

2026/10/20 23:41:33 阅读更多 →
华三AC WX5560H AP信道优化实战:解决信号满格却卡顿

华三AC WX5560H AP信道优化实战:解决信号满格却卡顿

前阵子在某园区处理无线投诉时&#xff0c;我碰到一个很典型的场景&#xff1a;AP 装了一堆、信号显示也是满格&#xff0c;但视频会议就是动不动卡成 PPT。当时很多人第一反应是带宽不够&#xff0c;可跑到华三 AC WX5560H 上一看&#xff0c;控制器负载很低&#xff0c;出口带…

2026/10/20 23:40:32 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

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

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

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

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

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

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/20 20:43:59 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 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/20 10:02:08 阅读更多 →
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/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练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/20 9:50:45 阅读更多 →