Ethan 发布的文章 - CorePlayers
首页
我的项目
708 智能控制台
Ethan认证中心
Ethan's ToDoList
Ethan's Tech Blog
好友链接
妙站分享
联系站长
搜 索
1
DDD领域驱动设计:从底层原理到生产级全链路落地实战
46 阅读
2
2026技术架构新趋势:从微服务回调到AI原生架构设计
46 阅读
3
Go + 云原生2026:从微服务到AI Infra的实战架构
36 阅读
4
事件驱动架构(EDA):从理论到项目落地的完整实践
36 阅读
5
Prompt 工程与 PGvector RAG 知识库:从文档 ETL 到查询增强的完整闭环
35 阅读
ALL
(79)
AI
(20)
前端
(24)
后端
(23)
Dify/Coze
(7)
架构设计
(6)
登录
/
注册
搜 索
标签搜索
AI Agent
边缘计算
RSC
虚拟线程
Java
Spring Boot 4
Vibe Coding
AI原生
SDD
全栈开发
高并发
Project Loom
性能优化
2026趋势
协议标准
工具调用
MCP协议
多Agent协作
CrewAI
Spring AI
EthanCcc
累计撰写
79
篇文章
累计收到
1
条评论
首页
栏目
ALL
AI
前端
后端
Dify/Coze
架构设计
页面
我的项目
708 智能控制台
Ethan认证中心
Ethan's ToDoList
Ethan's Tech Blog
好友链接
妙站分享
联系站长
用户登录
登录
注册
作者:Ethan
2025-06-05
浏览器事件循环与页面渲染机制完全指南
事件循环(Event Loop)是 JavaScript 运行时的核心机制,也是面试和实际开发中都无法绕开的关键知识点。不理解 Event Loop,你就无法解释 setTimeout 的延迟为什么不准、为什么某些动画会卡顿、以及为什么 async/await 的行为有时会出乎意料。本文将系统性地解析 Event Loop 和页面渲染的关系。JavaScript 的单线程本质JavaScript 被设计为单线程语言,主要原因是作为浏览器脚本语言,它需要操作 DOM——如果有两个线程同时操作同一个 DOM 节点,结果将不可预测。但单线程带来了一个问题:如果一个任务执行时间过长,页面就会"卡住"。Event Loop 正是为了解决这个问题而设计的。宏任务与微任务:事件循环的两层结构事件循环中,任务分为两种优先级:宏任务(MacroTask)——包括 script 整体、setTimeout、setInterval、I/O、UI 渲染、postMessage 等,每次事件循环取一个执行。微任务(MicroTask)——包括 Promise.then/catch/finally、MutationObserver、queueMicrotask、process.nextTick 等,宏任务执行完后一次性清空所有微任务。事件循环的完整流程浏览器的事件循环可以概括为以下循环过程:(1) 从宏任务队列中取出一个宏任务执行;(2) 执行过程中产生的微任务放入微任务队列;(3) 当前宏任务执行完毕后,清空微任务队列(包括微任务中新产生的微任务);(4) 如果需要,执行 UI 渲染(requestAnimationFrame 回调在此阶段);(5) 回到步骤 1,进入下一轮事件循环。console.log('1');\nsetTimeout(() => , 0);\nPromise.resolve().then(() => );\nconsole.log('6');\n// 输出:1 → 6 → 4 → 2 → 3 → 5async/await 的本质:Promise 的语法糖async function foo() \n// 等价于:\nfunction foo() );\n}Event Loop 与页面渲染的关系浏览器大约每 16.6ms(60fps)进行一次页面渲染。渲染发生在一轮事件循环的宏任务和微任务都执行完毕后。这意味着:微任务太多会阻塞渲染(如果微任务不断产生新的微任务,渲染将被无限推迟);requestAnimationFrame 在渲染前执行,适合做动画相关的计算;requestIdleCallback 在渲染后、下一轮循环前的空闲时间执行,适合做低优先级工作。// 危险:死循环微任务会永久阻塞渲染\nfunction blockingMicroTask() );\n}\n// requestIdleCallback:在浏览器空闲时执行非关键任务\nrequestIdleCallback((deadline) => \n});重排(Reflow)与重绘(Repaint)重排(Reflow):元素的几何属性(位置、尺寸)发生变化 → 浏览器重新计算布局。触发操作包括修改 width/height、添加/删除 DOM、改变字体大小、读取 offsetHeight 等布局属性。重绘(Repaint):元素的视觉属性(颜色、背景)发生变化但不影响布局 → 只重新绘制。重排一定触发重绘,但重绘不一定触发重排。重排的成本远高于重绘。// 错误:强制同步布局,每次读取 offsetHeight 都触发重排\nfor (let i = 0; i < 1000; i++) \n// 正确:批量读写分离\nconst width = element.offsetWidth; // 先读\nconst height = element.offsetHeight;\nelement.style.width = width + 10 + 'px'; // 后写\nelement.style.height = height + 10 + 'px';总结理解事件循环和渲染机制后,你在写代码时会自然地做出更好的决策:长列表用虚拟滚动、动画用 requestAnimationFrame、非关键任务用 requestIdleCallback、合并 DOM 操作避免强制同步布局。这些看似微小的优化,积累起来就是用户体验的巨大差异。
2025年06月05日
17
0
1
2025-06-04
2025年检索增强生成(RAG)最新进展与前沿技术
检索增强生成(Retrieval Augmented Generation, RAG)已从一个相对简单的"检索-生成"范式,演变为一个包含众多专业技术的复杂生态系统。2025年的发展趋势表明,RAG 的重点在于通过更高级的智能、适应性和上下文感知能力,来增强其流水线中的每一个组成部分。一、RAG 的演进历程最初的 RAG 系统采用固定的流水线作业:切块 → 向量化 → TopK检索 → 生成。然而实际应用中暴露了诸多问题,促使研究者将更复杂的推理能力嵌入 RAG 的各个阶段。2025年的演进可以概括为: Naive RAG:基础检索-生成两阶段 Advanced RAG:引入查询重写、重排序、上下文压缩 Self-RAG:系统评估自身中间步骤,动态调整策略 Agentic RAG:LLM 作为主动参与组件,自主规划检索策略 二、现代 RAG 的核心挑战1. 幻觉减少(Hallucination Reduction)确保 LLM 忠实地利用检索到的上下文进行生成仍是核心目标。CiteFix 和 DRAG 等技术专门针对这一问题,通过强制引用检索文档来约束生成行为。2. 知识陈旧性RAG 提供了无需完全重训练 LLM 即可注入最新知识的机制,但知识库的时效性管理成为了新的挑战。3. "Lost in the Middle" 问题LLM 倾向于关注文档的开头和结尾而忽略中间内容。先进的分块、重排序和上下文压缩技术致力于解决这一问题。三、先进的分块与嵌入策略语义分块:基于嵌入向量的语义相似性对句子进行分组,创建上下文感知的分块,取代传统的固定大小分块方法。文档结构感知分块:利用 Markdown 标题、章节、代码结构等确定分块边界,保留逻辑单元的完整性。Agentic 分块:让 LLM 自身根据语义含义和内容结构来决定最佳分块方式,最具实验性但也最有前景。四、鲁棒性 RAG:面向现实世界的设计2025年 RAG 研究的一个重要趋势是"面向鲁棒性的设计"。研究者正推动 RAG 从在干净数据集上追求准确率,转向在噪声数据、对抗性攻击、信息冲突等复杂条件下保持可靠性。代表性工作包括处理冲突信息的 Madam-RAG 和应对知识库投毒的 EcoSafeRAG。这种"防御性设计"对于企业采纳和高风险应用至关重要。五、总结与展望2025年的 RAG 正从简单的"检索-生成"管道演变为具备元学习能力的智能系统。未来的发展方向包括更强的自我适应能力、多模态检索集成以及更低的部署门槛。
2025年06月04日
29
0
1
2025-05-26
Dify Agent vs Workflow:AI 执行机制差异与选型指南
在开源大语言模型应用平台 Dify 中,Agent 和 Workflow 是两种最核心的任务执行机制。虽然它们都可以"驱动应用",但本质完全不同——Agent 更像一个带有策略和调用能力的 AI 决策系统,而 Workflow 是一个可以显式编排的可视化任务流程。核心定义Dify AgentAgent 是一种具有"策略 + 工具调用能力"的 AI 执行体,具备以下核心能力: 自主决策:支持 ReAct、Function Calling 等多种推理策略 工具集成:访问外部 API、数据库、插件,实现检索、查询、修改等操作 多轮推理:记住上下文、调用多个函数、形成循环思考 状态感知:结合用户输入、历史对话、系统变量做策略选择 Dify WorkflowWorkflow 是一个基于节点可视化的流程编排系统,相当于"无代码/低代码"编排的复杂 LLM 应用: 节点(Node):每个节点代表一个操作,如 LLM 调用、函数执行、HTTP 请求等 数据流:节点间通过结构化 JSON 传递数据 条件逻辑:支持 if/else、switch 分支、循环判断等 Agent 嵌入:Workflow 支持调用 Agent 节点,实现"流程 + 推理"的组合能力 功能维度深度对比 对比维度WorkflowAgent 控制方式显式流程图(节点+条件+顺序)策略驱动(ReAct/Function Call) 是否状态机是(可视化流程状态)否(推理链路通过 LLM 维护) 适合任务有清晰逻辑顺序的场景目标不清晰、需动态判断 多轮支持部分支持(依赖节点)原生支持上下文与记忆能力 工具调用内部节点明确调用由 LLM 推理触发 易调试性强,可追踪每个节点状态较弱,需结合日志分析 重复利用可模块化节点复用可创建共享 Agent 配置 架构职责分工在实际应用中,两者并非互斥而是互补: Workflow 是主流程控制器:决定哪个 Agent 上场,何时调用函数,是否继续执行 Agent 是内嵌的智能决策员:在节点内部调用 LLM + Tools 实现复杂任务解决 实际选型建议优先使用 Workflow:数据处理管道、CRM 自动化入库、WebHook 触发流程、有明确步骤顺序的业务场景。优先使用 Agent:需要多轮问答的客服系统、检索式 QA 系统、代码分析助手、需要自主探索的复杂任务。最佳实践:在 Workflow 中嵌入 Agent 节点,利用 Agent 处理不确定性高的子任务,Workflow 负责整体流程的调度与监控。
2025年05月26日
12
0
1
2025-05-18
TypeScript 高级类型编程:泛型、条件类型与类型体操实战
TypeScript 的类型系统是图灵完备的——这意味着你可以在类型层面进行"编程"。掌握高级类型不仅能提高代码的可维护性,更是编写高质量库和框架的必备技能。本文从泛型出发,逐步深入到条件类型和类型体操。泛型的本质:类型参数化泛型(Generics)让函数、接口、类可以接受类型参数,实现"一次定义,多处复用":// 没有泛型:每个类型都要写一遍\nfunction firstNumber(arr: number[]): number | undefined \nfunction firstString(arr: string[]): string | undefined \n// 使用泛型:一个函数适用所有类型\nfunction first(arr: T[]): T | undefined \n\nconst num = first([1, 2, 3]); // num: number\nconst str = first(['a', 'b']); // str: string泛型约束:限制类型参数的范围// 使用 extends 约束泛型\ninterface HasLength \nfunction logLength(arg: T): T \nlogLength('hello'); // string 有 length\nlogLength([1, 2, 3]); // array 有 length\nlogLength(123); // number 没有 length,编译错误\n\n// 使用 keyof 约束为对象属性的键\nfunction getProperty(obj: T, key: K): T[K] 条件类型:类型层面的 if/else条件类型是 TypeScript 类型系统的"控制流":// 基本语法:T extends U ? X : Y\ntype IsString = T extends string ? 'yes' : 'no';\ntype A = IsString; // 'yes'\ntype B = IsString; // 'no'\n\n// 实际应用:提取类型\ntype ExtractPromise = T extends Promise ? R : T;\ntype C = ExtractPromise; // string\ntype D = ExtractPromise; // number\n\n// 深层提取\ntype DeepExtractPromise = T extends Promise ? DeepExtractPromise : T;infer 关键字:从类型中提取信息// 提取函数返回值类型\ntype ReturnType = T extends (...args: any[]) => infer R ? R : never;\n// 提取函数参数类型\ntype FirstParam = T extends (first: infer F, ...rest: any[]) => any ? F : never;\n// 提取数组元素类型\ntype ArrayElement = T extends (infer E)[] ? E : never;模板字面量类型:类型层面的字符串操作type EventName = `on$`;\ntype ClickEvent = EventName; // 'onClick'\ntype ChangeEvent = EventName; // 'onChange'\n\n// 实战:类型安全的事件系统\ntype EventMap = ; change: };\ntype EventHandlers = `]: (data: EventMap[K]) => void;\n};\n// ) => void;\n// onChange: (data: ) => void }映射类型与工具类型实战interface User \n// Partial:所有属性变为可选\ntype PartialUser = Partial;\n// Required:所有属性变为必填\ntype RequiredUser = Required;\n// Pick:选取部分属性\ntype UserPreview = Pick;\n// Omit:排除部分属性\ntype UserWithoutId = Omit;\n// Record:构造对象类型\ntype PageRoute = Record;实战:类型安全的 API 请求封装// 定义 API 接口映射\ninterface ApiMap ;\n '/api/users': ;\n}\ninterface ApiResultMap ;\n '/api/users': ;\n}\n\n// 类型安全的请求函数\nasync function request(\n url: T, params: ApiMap[T]\n): Promise );\n return response.json();\n}\n\n// 使用时获得完整的类型提示和检查\nconst user = await request('/api/user', ); // user.name 有自动补全总结TypeScript 的类型系统是一把双刃剑。用得好的类型能成为最好的文档和最可靠的守卫;用得过度的类型会成为维护的负担。掌握高级类型的关键在于:先解决实际问题,再追求类型的优雅。
2025年05月18日
12
0
1
2025-05-17
Rust vs Go:2025 微服务性能基准测试深度对比
在构建微服务架构时,Rust 和 Go 是两个最受关注的后端语言选择。本文基于 2025 年最新版本(Rust 1.75 和 Go 1.22)的实际基准测试,深入对比两者在微服务场景下的性能表现。测试环境 组件规格 CPUAMD Ryzen 9 7950X (16核32线程) 内存64GB DDR5-6000 系统Ubuntu 24.04 LTS Rust1.75.0 (Axum框架) Go1.22.3 (Gin框架) HTTP 服务性能对比 指标Rust (Axum)Go (Gin)差异 吞吐量 (req/s)187,450142,380Rust +31.7% P50 延迟 (ms)0.520.68Rust -23.5% P99 延迟 (ms)1.271.85Rust -31.4% 内存使用 (MB)18.327.6Rust -33.7% 关键性能差异分析1. P99 延迟尖峰问题Go 在 P99 延迟上出现了明显的尖峰,主要原因是垃圾回收(GC)的 Stop-The-World 暂停。尽管 Go 1.22 显著改进了 GC 延迟,但在高并发场景下仍可观察到周期性的延迟抖动。Rust 的无 GC 所有权模型从根本上避免了这一问题。2. 内存使用效率Rust 的零成本抽象模型使其在内存使用上比 Go 节省约 33.7%。对于大规模部署而言,这意味着在相同硬件上可以运行更多实例,直接转化为云成本的节约。3. 并发处理能力Go 的 Goroutine 调度器极为高效,10,000 个并发连接的测试中两者均表现优异。但在 CPU 密集型计算场景下,Rust 的 async/await 模型展现出更好的可预测性能。Rust 常见陷阱 学习曲线陡峭:所有权和生命周期概念需要时间消化 编译时间较长:大型项目的增量编译仍需优化 异步生态碎片化:需要在 Tokio、async-std 等运行时之间做选择 Go 常见陷阱 GC 延迟抖动:对延迟敏感的应用需特别注意 零值陷阱:nil 指针和零值可能导致隐蔽的 bug 没有枚举类型:缺乏完善的代数数据类型支持 选型建议选择 Rust 的场景:需要极致性能和可预测延迟的系统级组件、高频交易系统、边缘计算节点、数据密集型管道处理。选择 Go 的场景:快速迭代的 API 服务、团队开发效率优先的项目、需要简单运维的云原生微服务、初创团队的 MVP 开发。
2025年05月17日
11
0
1
1
...
11
12
13
...
16