news 2026/3/2 7:12:13

前端老铁别再混用 Promises 和 Observables 了!搞懂区别少踩80%

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
前端老铁别再混用 Promises 和 Observables 了!搞懂区别少踩80%


前端老铁别再混用 Promises 和 Observables 了!搞懂区别少踩80%

  • 前端老铁别再混用 Promises 和 Observables 了!搞懂区别少踩80%的坑
    • Promise 是啥?——"一次性暖男"
    • Observable 是啥?——"海后级多面手"
    • 把他俩拖进同一个场景,真刀真枪比一比
      • 场景 1:搜索框防抖 ——Promise 瞬间自闭
        • Promise 版(手搓 setTimeout,回调地狱预定):
        • Observable 版(一行操作符搞定):
      • 场景 2:文件上传带进度条 ——Promise 直接抓瞎
        • Promise 版(fetch 根本拿不到 progress 事件):
        • Observable 版(XMLHttpRequest 套壳,progress 稳稳到手):
      • 场景 3:WebSocket 实时聊天 ——Promise 连门都进不去
        • Promise 版(直接无解,Promise 只能拿一次值,流式数据天生绝缘):
        • Observable 版(封装 WebSocket,消息流丝滑切换):
    • 把 Observable 当 Promise 用?——from 和 lastValueFrom 了解一下
      • 1. Promise → Observable(from 一行解决)
      • 2. Observable → Promise(lastValueFrom,Angular 13+ 官方推荐)
    • 内存泄漏大坑:unsubscribe 不写,老板请喝茶
      • 正确姿势 1:手动 unsubscribe
      • 正确姿势 2:async 管道(Angular 推荐,零泄漏)
    • 性能对比:数据说话,别瞎吹
    • 私藏技巧大放送,拿走不谢
    • 什么时候该选谁?一张草图秒懂
    • 尾声:别盲目崇拜,也别无脑黑

前端老铁别再混用 Promises 和 Observables 了!搞懂区别少踩80%的坑

友情提示:本文全程碎碎念,代码管够,吐槽管饱,阅读时建议配一杯冰美式,防止打瞌睡。


Promise 是啥?——“一次性暖男”

先给 Promise 发张好人卡:它就像那种只暖你一次的暖男,说出去的话泼出去的水,一旦 resolve 就彻底锁死,想反悔?门都没有。

最经典的打开方式:

// 1. 原生 fetch,返回 Promisefetch('/api/user').then(res=>res.json()).then(data=>console.log('用户',data)).catch(err=>console.error('凉了',err));

看起来人畜无害,对吧?但一旦场景升级,暖男瞬间变"猪队友":

  • 用户狂点搜索按钮,Promise 管你点几次,全部请求照单全收,回来顺序还给你乱成一锅粥;
  • WebSocket 推股票行情,Promise 只能拿一次数据,想持续监听?对不起,臣妾做不到
  • 中途想取消请求?不好意思,Promise 没长腿,跑不了也死不掉

总结一句:Promise 就是"一次交付,终身负责",简单场景够用,复杂场景直接原地爆炸。


Observable 是啥?——“海后级多面手”

如果 Promise 是暖男,那 Observable 就是海后,备胎成群、操作拉满,还能随时拉黑(unsubscribe):

// 1. 先整一个能发多次的数据流import{interval}from'rxjs';interval(1000)// 每秒吐一个数字.subscribe(n=>console.log('第',n,'秒'));

看到没?数据可以一直流,你只要不喊停,她就不停;想甩了?一句话:

constsub=interval(1000).subscribe(...);sub.unsubscribe();// 拉黑,江湖再见

而且海后技能树深不见底:map、filter、merge、switchMap、debounceTime……花式操作多到你想不到。后面实战挨个给你拆解,别急。


把他俩拖进同一个场景,真刀真枪比一比

场景 1:搜索框防抖 ——Promise 瞬间自闭

需求:用户输入停 300ms 再发请求,减少 QPS。

Promise 版(手搓 setTimeout,回调地狱预定):
lettimer=null;functionsearch(keyword){clearTimeout(timer);timer=setTimeout(async()=>{constres=awaitfetch(`/api/search?q=${keyword}`);constdata=awaitres.json();console.log('结果',data);},300);}

写起来就一股 jQuery 时代的味道,而且如果用户输入太快,旧请求仍可能后返回,结果顺序错乱,体验拉垮。

Observable 版(一行操作符搞定):
import{fromEvent}from'rxjs';import{debounceTime,distinctUntilChanged,switchMap}from'rxjs/operators';fromEvent(inputDom,'input').pipe(debounceTime(300),// 防抖 300msdistinctUntilChanged(),// 内容没变就跳过switchMap(e=>fetch(`/api/search?q=${e.target.value}`))// 新请求直接顶掉旧请求).subscribe(res=>console.log('结果',res));

switchMap会自动取消上次未返回的请求,保证最新输入对应最新结果,这波操作 Promise 只能原地流泪。


场景 2:文件上传带进度条 ——Promise 直接抓瞎

需求:展示实时上传百分比。

Promise 版(fetch 根本拿不到 progress 事件):
// fetch 不支持 onprogress,只能干等结束,进度条随缘awaitfetch('/upload',{method:'POST',body:file});console.log('上传完了,进度条全靠 P 图');
Observable 版(XMLHttpRequest 套壳,progress 稳稳到手):
import{Observable}from'rxjs';functionupload(file){returnnewObservable(observer=>{constxhr=newXMLHttpRequest();xhr.open('POST','/upload');// 进度事件xhr.upload.onprogress=(e)=>{if(e.lengthComputable){constpercent=Math.round(e.loaded/e.total*100);observer.next(percent);// 实时把百分比推出去}};xhr.onload=()=>observer.complete();xhr.onerror=err=>observer.error(err);xhr.send(file);});}// 使用upload(file).subscribe(p=>(progressBar.style.width=p+'%'));

实时百分比推送,Promise 只能望洋兴叹。


场景 3:WebSocket 实时聊天 ——Promise 连门都进不去

需求:接收持续的消息流。

Promise 版(直接无解,Promise 只能拿一次值,流式数据天生绝缘):
// Promise 无法处理持续推送,只能告辞
Observable 版(封装 WebSocket,消息流丝滑切换):
import{webSocket}from'rxjs/webSocket';constws$=webSocket('wss://echo.websocket.org');// 发消息ws$.next({msg:'老铁在吗?'});// 收消息ws$.subscribe(msg=>console.log('收到',msg),err=>console.error('出错',err),()=>console.log('连接关了'));

消息想发就发,想收就收,背压控制、重连机制都能用 operators 继续堆,Promise 只能原地解散。


把 Observable 当 Promise 用?——from 和 lastValueFrom 了解一下

有时候你只想快速把现有 Promise 代码迁移成流,或者反过来把流伪装成 Promise 给老模块调用,RxJS 给你两条捷径:

1. Promise → Observable(from 一行解决)

import{from}from'rxjs';from(fetch('/api/user'))// 把 Promise 包成 Observable.subscribe(res=>console.log(res));

2. Observable → Promise(lastValueFrom,Angular 13+ 官方推荐)

import{lastValueFrom}from'rxjs';// 假设 userService 返回的是 Observableconstusers=awaitlastValueFrom(userService.getUsers$());console.log('用户列表',users);

注意,老版本里的toPromise()已被废弃,新项目别再用,免得以后升级哭瞎。


内存泄漏大坑:unsubscribe 不写,老板请喝茶

Observable 功能多,坑位也多,最臭名昭著的就是内存泄漏:

ngOnInit(){this.userService.getUsers$().subscribe(users=>this.users=users);// 没取消订阅 → 组件销毁后回调还在 → 内存飙升 → 页面越用越卡}

正确姿势 1:手动 unsubscribe

privatesub=newSubscription();ngOnInit(){this.sub.add(this.userService.getUsers$().subscribe(users=>this.users=users));}ngOnDestroy(){this.sub.unsubscribe();// 统一释放}

正确姿势 2:async 管道(Angular 推荐,零泄漏)

// 组件里users$=this.userService.getUsers$();// 模板里<div*ngFor="let u of users$ | async">{{u.name}}</div>

模板自动帮你订阅 + 销毁,手残党福音


性能对比:数据说话,别瞎吹

在 ABP 框架里有人跑过实际基准 :

场景Promise 耗时Observable 耗时备注
单次 HTTP120ms125ms基本打平
高频更新不支持5ms/次Observable 完胜
内存占用稍高操作符开销
取消操作不支持即时释放Observable 完胜

结论:单次请求两者一样快,但流式、可取消、高频场景 Observable 碾压;包体积多出的十几 KB,换这些特性不亏


私藏技巧大放送,拿走不谢

  1. switchMap 防抖动请求:比 AbortController 优雅,旧请求自动取消;
  2. debounceTime + distinctUntilChanged:搜索框标配,300ms 防抖 + 相同输入跳过;
  3. retry + catchError:网络抖动自动重试,失败还能降级到本地缓存;
  4. 按需引入操作符import { map } from 'rxjs/operators'一句省几十 KB,别import *一把梭;
  5. 调试想打 logtap(val => console.log('路过', val)),无副作用,调试神器

什么时候该选谁?一张草图秒懂

场景用 Promise用 Observable
一次性 HTTP✅ 简单直接也可以,但杀鸡用牛刀
持续事件流(WebSocket、输入)❌ 不支持✅ 天生为此而生
需要取消/重试❌ 做不到✅ operators 安排
包体积敏感(营销落地页)✅ 原生无依赖❌ 需引 RxJS
团队新手多,排期紧✅ 人人会❌ 学习成本

一句话总结:简单一次性 Promise 足够,流式复杂 Observable 真香


尾声:别盲目崇拜,也别无脑黑

Promise 就像老牌瑞士军刀,随手能用;Observable 更像电动工具箱,功能炸裂但要读说明书。两者不是对立,而是互补——知道差异、选对场景、少踩 80% 的坑,才是本文最想给你的忠告。

下次leader再让你"全都改成 Observable",你可以甩他这篇文章;同事再嘲笑"Promise 老掉牙",你也可以把防抖搜索的代码糊他脸上。技术选型,适合最好能 hold 住最妙

代码写完了,咖啡也凉了,去重构吧,老铁!
https://blog.csdn.net/gitblog_00944/article/details/148392188

欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。

推荐:DTcode7的博客首页。
一个做过前端开发的产品经理,经历过睿智产品的折磨导致脱发之后,励志要翻身农奴把歌唱,一边打入敌人内部一边持续提升自己,为我们广大开发同胞谋福祉,坚决抵制睿智产品折磨我们码农兄弟!


专栏系列(点击解锁)学习路线(点击解锁)知识定位
《微信小程序相关博客》持续更新中~结合微信官方原生框架、uniapp等小程序框架,记录请求、封装、tabbar、UI组件的学习记录和使用技巧等
《AIGC相关博客》持续更新中~AIGC、AI生产力工具的介绍,例如stable diffusion这种的AI绘画工具安装、使用、技巧等总结
《HTML网站开发相关》《前端基础入门三大核心之html相关博客》前端基础入门三大核心之html板块的内容,入坑前端或者辅助学习的必看知识
《前端基础入门三大核心之JS相关博客》前端JS是JavaScript语言在网页开发中的应用,负责实现交互效果和动态内容。它与HTML和CSS并称前端三剑客,共同构建用户界面。
通过操作DOM元素、响应事件、发起网络请求等,JS使页面能够响应用户行为,实现数据动态展示和页面流畅跳转,是现代Web开发的核心
《前端基础入门三大核心之CSS相关博客》介绍前端开发中遇到的CSS疑问和各种奇妙的CSS语法,同时收集精美的CSS效果代码,用来丰富你的web网页
《canvas绘图相关博客》Canvas是HTML5中用于绘制图形的元素,通过JavaScript及其提供的绘图API,开发者可以在网页上绘制出各种复杂的图形、动画和图像效果。Canvas提供了高度的灵活性和控制力,使得前端绘图技术更加丰富和多样化
《Vue实战相关博客》持续更新中~详细总结了常用UI库elementUI的使用技巧以及Vue的学习之旅
《python相关博客》持续更新中~Python,简洁易学的编程语言,强大到足以应对各种应用场景,是编程新手的理想选择,也是专业人士的得力工具
《sql数据库相关博客》持续更新中~SQL数据库:高效管理数据的利器,学会SQL,轻松驾驭结构化数据,解锁数据分析与挖掘的无限可能
《算法系列相关博客》持续更新中~算法与数据结构学习总结,通过JS来编写处理复杂有趣的算法问题,提升你的技术思维
《IT信息技术相关博客》持续更新中~作为信息化人员所需要掌握的底层技术,涉及软件开发、网络建设、系统维护等领域的知识
《信息化人员基础技能知识相关博客》无论你是开发、产品、实施、经理,只要是从事信息化相关行业的人员,都应该掌握这些信息化的基础知识,可以不精通但是一定要了解,避免日常工作中贻笑大方
《信息化技能面试宝典相关博客》涉及信息化相关工作基础知识和面试技巧,提升自我能力与面试通过率,扩展知识面
《前端开发习惯与小技巧相关博客》持续更新中~罗列常用的开发工具使用技巧,如 Vscode快捷键操作、Git、CMD、游览器控制台等
《photoshop相关博客》持续更新中~基础的PS学习记录,含括PPI与DPI、物理像素dp、逻辑像素dip、矢量图和位图以及帧动画等的学习总结
日常开发&办公&生产【实用工具】分享相关博客》持续更新中~分享介绍各种开发中、工作中、个人生产以及学习上的工具,丰富阅历,给大家提供处理事情的更多角度,学习了解更多的便利工具,如Fiddler抓包、办公快捷键、虚拟机VMware等工具

吾辈才疏学浅,摹写之作,恐有瑕疵。望诸君海涵赐教。望轻喷,嘤嘤嘤

非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。愿斯文对汝有所裨益,纵其简陋未及渊博,亦足以略尽绵薄之力。倘若尚存阙漏,敬请不吝斧正,俾便精进!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/19 5:45:04

Hunyuan-HY-MT1.5实战教程:构建私有化翻译SaaS服务完整流程

Hunyuan-HY-MT1.5实战教程&#xff1a;构建私有化翻译SaaS服务完整流程 随着全球化业务的不断扩展&#xff0c;高质量、低延迟、可定制的翻译服务成为企业出海、内容本地化和多语言沟通的核心需求。然而&#xff0c;依赖公有云翻译API存在数据隐私泄露、调用成本高、定制能力弱…

作者头像 李华
网站建设 2026/2/23 2:58:14

Hunyuan翻译模型如何适配4090D?算力匹配部署教程

Hunyuan翻译模型如何适配4090D&#xff1f;算力匹配部署教程 1. 引言&#xff1a;为何选择HY-MT1.5与4090D组合&#xff1f; 随着多语言交流需求的爆发式增长&#xff0c;高质量、低延迟的翻译模型成为智能应用的核心组件。腾讯开源的混元翻译大模型HY-MT1.5系列&#xff0c;凭…

作者头像 李华
网站建设 2026/2/26 1:31:55

HY-MT1.5-7B怎么快速上手?WMT25优胜模型部署入门必看

HY-MT1.5-7B怎么快速上手&#xff1f;WMT25优胜模型部署入门必看 1. 引言&#xff1a;腾讯开源的高性能翻译大模型 随着多语言交流需求的不断增长&#xff0c;高质量、低延迟的机器翻译技术成为AI应用落地的关键环节。腾讯近期开源了混元翻译大模型1.5版本&#xff08;HY-MT1.…

作者头像 李华
网站建设 2026/2/21 5:15:16

Hunyuan翻译模型支持术语干预?企业级定制实战案例

Hunyuan翻译模型支持术语干预&#xff1f;企业级定制实战案例 近年来&#xff0c;随着全球化业务的加速拓展&#xff0c;高质量、可定制的机器翻译需求日益增长。传统商业翻译API虽然稳定&#xff0c;但在术语一致性、上下文理解与数据隐私方面存在明显短板。腾讯开源的混元翻…

作者头像 李华
网站建设 2026/3/1 2:00:41

HY-MT1.5-7B WMT25夺冠技术揭秘:高性能翻译部署教程

HY-MT1.5-7B WMT25夺冠技术揭秘&#xff1a;高性能翻译部署教程 1. 引言&#xff1a;腾讯开源的混元翻译大模型 在多语言交流日益频繁的今天&#xff0c;高质量、低延迟的机器翻译已成为全球化应用的核心基础设施。近期&#xff0c;腾讯AI Lab正式开源了其最新一代翻译大模型—…

作者头像 李华
网站建设 2026/2/27 5:08:19

5个开源翻译大模型部署教程:HY-MT1.5镜像免配置,一键启动实战推荐

5个开源翻译大模型部署教程&#xff1a;HY-MT1.5镜像免配置&#xff0c;一键启动实战推荐 1. 引言 1.1 开源翻译模型的现实需求 在全球化加速和多语言内容爆发的背景下&#xff0c;高质量、低延迟的机器翻译能力已成为企业出海、内容本地化、跨语言交流等场景的核心基础设施。…

作者头像 李华