JavaScript笔记(五)Promise对象

一、Promise 是什么(不是“异步回调的语法糖”)

Promise 是 JavaScript 中用于处理异步操作的对象,它代表了一个异步操作的最终完成(或失败)及其结果值。

一句话本质

Promise 是一个“状态机 + 回调管理器”,用来描述“一个未来才会确定结果的值”。

Promise 的三大特征(规范层面)

  • pending(进行中):初始状态
  • fulfilled(已成功):操作成功完成
  • rejected(已失败):操作失败
  1. 状态不可逆
    状态转换是单向的:
    • pending → fulfilled
    • pending → rejected
    • 一旦改变,永远不可再变

then 永远异步执行(微任务)

即使 resolve 是同步调用的

结果值只认第一次

resolve(1)resolve(2)// 无效reject(3)// 无效

那为什么总说 “Promise resolved 了”?(关键)

Promise 真正的“官方状态”只有 3 个

Promise/A+ & ECMAScript 规范中:

pending fulfilled rejected 

没有 resolved 这个状态


resolved ≠ fulfilled

resolved 是一个“动词 / 过程”,不是状态

规范里的原话是:

Resolve a promise with x

意思是:

尝试用某个值 x 去“解析(resolve)”Promise

用一句话精确区分(面试级)

resolved 表示 Promise 已经“被处理过”,
但它最终可能是 fulfilled,也可能是 rejected

换句话说:

resolved ↓ fulfilled 或 rejected 

⚠️ 注意:
一旦进入 resolved 流程,就不再是 pending

日常口语表达(工程师黑话)
“这个 Promise resolve 了” 

通常真正意思是:

  • then 被触发了
  • 异步成功了
  • 不是 pending 了

👉 不是规范用语

一个非常容易被问懵的面试题
Q:Promise.resolve(Promise.reject(1)) 的状态是什么?
Promise.resolve(Promise.reject(1)).then(()=> console.log('fulfilled'),err=> console.log('rejected', err))
正确理解:
  • 外层 Promise 被 resolve 了
  • 但 resolve 的值是一个 rejected Promise
  • 所以最终状态是:
rejected(1) 

⚠️ 这就是 “resolved ≠ fulfilled” 的最好例子

创建 Promise

const promise =newPromise((resolve, reject)=>{// 异步操作setTimeout(()=>{const success =true;if(success){resolve('操作成功');}else{reject(newError('操作失败'));}},1000);});

二、Promise 的状态模型(核心)

 ┌─────────────┐ │ pending │ └──────┬──────┘ │ ┌───────────┴───────────┐ │ │ ┌─────────────┐ ┌─────────────┐ │ fulfilled │ │ rejected │ └─────────────┘ └─────────────┘ 

内部必然有的字段(实现角度)

{status:'pending'|'fulfilled'|'rejected',value: any,reason: any,onFulfilledCallbacks:[],onRejectedCallbacks:[]}
这不是猜的,是 Promise/A+ 实现的必然结构

三、Promise 的常见方法

then() - 处理成功和失败

then方法可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为fulfilled时调用,第二个回调函数是Promise对象的状态变为rejected时调用。then方法返回的是一个新的Promise对象实例;因此可以用链式写法,即then的后面再调用另一个then方法。

promise.then((result)=>{ console.log('成功:', result);},(error)=>{ console.log('失败:', error);});
catch() - 捕获错误

相当于第二个回调函数指向reject;catch方法还有一个作用,就是在执行resolve回调时,如果出现错误抛出异常,不会停止运行,而是进入catch方法中。

promise .then(result=> console.log(result)).catch(error=> console.error('错误:', error));
finally() - 无论成功失败都执行

finally方法用于指定不管Promise对象最后状态如何,都会执行finally。finally方法的回调函数不接收任何参数。这表明finally方法里面的操作应与状态无关,不依赖于Promise的执行结果。

promise .then(result=> console.log(result)).catch(error=> console.error(error)).finally(()=> console.log('操作结束'));
all() - 所有都成功

方法接收一个平行任务。它接收一个数组;数组的每一项都是一个Promise对象;当数组的每一项的状态都是fulfilled的时候,all方法的状态会变成fulfilled。如果有一项状态变成rejected,那么all方法的状态就会变成rejected

  • 全部 fulfilled → fulfilled(数组)
  • 任意 rejected → 立即 rejected(短路)
const p1 = Promise.resolve(1);const p2 = Promise.resolve(2);const p3 = Promise.resolve(3); Promise.all([p1, p2, p3]).then(values=> console.log(values));// [1, 2, 3].catch(error=> console.error(error));
race() - 最先完成的

和all方法一样,接收的参数是一个每项都是Promise的数组。但是与all不同的是,当最先执行的事件完成之后,就直接返回Promise对象的值,如果第一个Promise对象状态是fulfilled,那自身状态就是fulfilled。

  • 谁先 settle,用谁
const p1 =newPromise(resolve=>setTimeout(resolve,500,'快'));const p2 =newPromise(resolve=>setTimeout(resolve,1000,'慢')); Promise.race([p1, p2]).then(value=> console.log(value));// "快"
any() - 任意一个成功

只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态;如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态。
Promise.any()跟Promise.race()方法很像,只有一点不同,就是Promise.any()不会因为某个 Promise 变成rejected状态而结束,必须等到所有参数 Promise 变成rejected状态才会结束。

  • 任意 fulfilled → fulfilled
  • 全 rejected → rejected(AggregateError)
Promise.any([p1, p2]).then(value=> console.log(value));

三、then 的真正含义(99%的人理解错)

then ≠ 注册回调这么简单

p.then(onFulfilled, onRejected)

then 做了 3 件极其重要的事:

  1. 返回一个新的 Promise(链式调用的根源)
  2. 把回调包装成“微任务”
  3. 处理返回值,决定新 Promise 的状态

then 的返回规则(重点)

then 回调返回值新 Promise 状态
普通值fulfilled,值为返回值
Promise等这个 Promise
thenable 对象按 Promise 解析
throw errorrejected
不写回调值穿透 / 错误冒泡
Promise.resolve(1).then(v=> v +1).then(v=> Promise.resolve(v +1)).then(v=>{throw'err'}).catch(e=> console.log(e))

四、Promise 链为什么不会“嵌套地狱”?

核心原因:then 返回新 Promise

const p2 = p1.then(...)

本质结构:

p1 ──then──▶ p2 ──then──▶ p3 

而不是:

p1 └── then └── then └── then 

Promise Resolution Procedure(规范核心)

伪代码:

if(x === promise)throw TypeError if(x is Promise) adopt its state if(x is object/function&& has then) call then elseresolve(x)
这套规则就是防止循环引用、防止多次 resolve、防止同步 thenable 乱入

五、Promise 的微任务本质(Event Loop 级别)

经典面试题

console.log(1) Promise.resolve().then(()=>{ console.log(2)})setTimeout(()=>{ console.log(3)}) console.log(4)

输出顺序:

1 4 2 3 

原因

  • Promise.then → Microtask
  • setTimeout → Macrotask

async / await 本质

asyncfunctionfoo(){awaitbar() console.log(1)}

等价于:

functionfoo(){return Promise.resolve(bar()).then(()=>{ console.log(1)})}

👉 await = Promise.then 的语法糖


六、Promise 的“错误传播机制”

错误冒泡规则

  1. throw 等价于 reject
  2. 下游 then 没有 onRejected → 继续向下冒泡
  3. .catch() 本质是 .then(null, onRejected)
Promise.resolve().then(()=>{thrownewError('boom')}).then(()=>{ console.log('never')}).catch(err=>{ console.log(err.message)})

一个隐蔽坑(非常高级)

Promise.resolve().then(()=>{setTimeout(()=>{thrownewError('boom')})}).catch(()=>{ console.log('catch?')})

👉 catch 不会捕获

原因:

Promise 只能捕获 then 链中的同步异常 & 返回的 Promise 异常

七、Promise 的核心(面试杀器)

不要求背,但必须理解

最小核心能力:

then(onFulfilled, onRejected){returnnewPromise((resolve, reject)=>{// 状态判断// 回调队列// 微任务包装// 返回值处理(Promise Resolution)})}

面试官真正想问的是:

  • 你理解“状态不可逆”吗?
  • 你知道 then 为什么返回新 Promise 吗?
  • 你明白微任务队列吗?
  • 你理解 Promise Resolution Procedure 吗?

八、什么时候不该用 Promise(架构视角)

Promise 的局限性

  • 无法取消Promise,中途无法取消
  • 错误处理需要谨慎;如果不设置回调函数,Promise的内部抛出的错误不会反映到外部
  • 需要配合 async/await 使用更佳
  • 当处于pending状态时,无法得知目前进行到哪个阶段了

❌ 滥用 Promise:

  • 复杂流程控制(应使用 async/await + try/catch)
  • 大量并发控制(应配合并发池)
  • 事件型逻辑(Promise 不可多次 resolve)

✅ Promise 最适合:

  • 一次性结果
  • IO 抽象
  • 组合式异步

九、总结

Promise 是现代 JavaScript 异步编程的核心,理解它的工作原理和最佳实践对于编写健壮的异步代码至关重要。

Promise 解决的不是“异步”,而是
“用可组合、可推理的方式描述未来值的状态变化”

Read more

医疗AI场景下算法编程的深度解析(2026新生培训讲稿)(八)

医疗AI场景下算法编程的深度解析(2026新生培训讲稿)(八)

第15章 模型融合与集成策略 在机器学习竞赛和实际应用中,模型融合(Model Ensemble)是提升预测性能的利器。通过组合多个不同的基模型,集成策略能够综合各个模型的优势,抵消单个模型的偏差和方差,从而获得比任何单一模型更稳定、更准确的预测结果。在医疗AI领域,模型融合同样具有重要价值——面对复杂多模态的医疗数据,单一模型往往难以全面捕捉所有信息,而融合多个异质模型可以提升诊断的鲁棒性和准确性。本章将从集成学习的基本思想出发,系统介绍常见的模型融合方法,包括投票法、平均法、Stacking、Blending等,并通过实战案例展示如何构建融合模型来提升疾病预测性能。 15.1 集成学习的基本思想 集成学习(Ensemble Learning)的核心思想是“三个臭皮匠,顶个诸葛亮”——通过结合多个学习器来完成学习任务,通常可以获得比单一学习器更优越的泛化性能。根据个体学习器的生成方式,集成学习主要分为两大类: * Bagging:并行训练多个独立的基学习器,然后通过平均或投票进行结合。典型代表是随机森林。Bagging主要降低方差。 * Boosting:串行训练基学习

By Ne0inhk

保姆级教程:Windows本地部署Ollama+OpenClaw,打造你的AI赚钱系统(APP开发/量化/小说/剪辑)

摘要:想用AI搞钱但卡在技术门槛?本文手把手教你用一台Windows电脑,零成本本地部署Ollama大模型+OpenClaw智能中枢,赋予AI开发APP、量化分析、编写小说、剪辑辅助等“赚钱技能”。全程无需编程基础,跟着鼠标点、照着命令敲,即可拥有24小时待命的AI员工。 一、写在前面 很多朋友对AI变现跃跃欲试,却常被这些问题劝退: * 云端部署太贵,API调用怕浪费钱 * 技术文档看不懂,不知道从哪下手 * 数据隐私担忧,不敢把敏感资料上传 其实,你手头那台Windows电脑完全能胜任!本文将带你搭建一套完全本地化、免费、可扩展的AI生产力系统,让AI帮你写代码、分析表格、生成文案、处理视频,真正把AI变成你的“赚钱工具”。 系统架构: * 本地大脑:Ollama + DeepSeek模型,负责理解任务、生成内容 * 智能中枢:OpenClaw(原名OpenClaude),负责调用各类工具(Skill) * 赚钱技能:通过安装Skill包,让AI具备特定领域的实操能力 适用人群:

By Ne0inhk
人工智能:自然语言处理在客户服务领域的应用与实战

人工智能:自然语言处理在客户服务领域的应用与实战

人工智能:自然语言处理在客户服务领域的应用与实战 学习目标 💡 理解自然语言处理(NLP)在客户服务领域的应用场景和重要性 💡 掌握客户服务领域NLP应用的核心技术(如聊天机器人、意图识别、情感分析) 💡 学会使用前沿模型(如BERT、GPT-3)进行客户服务文本分析 💡 理解客户服务领域的特殊挑战(如实时性要求、多语言处理、用户体验) 💡 通过实战项目,开发一个客户服务聊天机器人应用 重点内容 * 客户服务领域NLP应用的主要场景 * 核心技术(聊天机器人、意图识别、情感分析) * 前沿模型(BERT、GPT-3)在客户服务领域的使用 * 客户服务领域的特殊挑战 * 实战项目:客户服务聊天机器人应用开发 一、客户服务领域NLP应用的主要场景 1.1 聊天机器人 1.1.1 聊天机器人的基本概念 聊天机器人是通过自然语言与用户进行交互的程序。在客户服务领域,聊天机器人的主要应用场景包括: * 客户服务:回答客户的问题(如“如何退货”、“商品价格”

By Ne0inhk
AI 时代,鸿蒙 App 还需要传统导航结构吗?

AI 时代,鸿蒙 App 还需要传统导航结构吗?

子玥酱(掘金 / 知乎 / ZEEKLOG / 简书 同名) 大家好,我是子玥酱,一名长期深耕在一线的前端程序媛 👩‍💻。曾就职于多家知名互联网大厂,目前在某国企负责前端软件研发相关工作,主要聚焦于业务型系统的工程化建设与长期维护。 我持续输出和沉淀前端领域的实战经验,日常关注并分享的技术方向包括前端工程化、小程序、React / RN、Flutter、跨端方案, 在复杂业务落地、组件抽象、性能优化以及多端协作方面积累了大量真实项目经验。 技术方向:前端 / 跨端 / 小程序 / 移动端工程化 内容平台:掘金、知乎、ZEEKLOG、简书 创作特点:实战导向、源码拆解、少空谈多落地 文章状态:长期稳定更新,大量原创输出 我的内容主要围绕 前端技术实战、真实业务踩坑总结、框架与方案选型思考、行业趋势解读 展开。文章不会停留在“API 怎么用”,而是更关注为什么这么设计、在什么场景下容易踩坑、

By Ne0inhk