了解Promise
2025-08-18 15:42
“当我们学会管理异步,代码世界才会真正清晰。”
为什么需要 Promise?
写 JavaScript 的过程中,最让人头疼的就是“异步”。浏览器请求数据、定时器、文件操作……这些事情都不会立刻返回结果。于是,最常见的解决方案就是回调函数(callback)。但随着逻辑变复杂,回调会层层嵌套,形成著名的“回调地狱”:
JSgetData(function(a){ parseData(a, function(b){ filterData(b, function(c){ saveData(c, function(result){ console.log(result); }); }); }); });
这种结构可读性极差,调试也非常困难。于是,Promise 出现了,它用一种更优雅的方式来管理异步流程。
Promise 是什么?
简单来说,Promise 是一个代表未来结果的容器。 它有三种状态:
pending
(进行中)fulfilled
(已完成)rejected
(已失败) 一旦状态从 pending 变成 fulfilled 或 rejected,就会“锁定”,无法再更改。这种设计保证了异步结果的确定性。
基本用法
创建一个 Promise:
JSconst p = new Promise((resolve, reject) => { setTimeout(() => { resolve("成功的数据"); // 或者 reject("出错了"); }, 1000); }); p.then(data => { console.log("成功:", data); }).catch(err => { console.error("失败:", err); });
和回调对比,Promise 写法显得更加线性,逻辑关系清晰很多。
链式调用
Promise 最大的优势在于可以通过 then
链接多个异步操作:
JSfetch("/api/user") .then(res => res.json()) .then(user => fetch(`/api/order/${user.id}`)) .then(res => res.json()) .then(order => console.log(order)) .catch(err => console.error("出错了:", err));
通过 catch
,我们可以统一处理链路上的错误,而不需要在每一步都写错误回调。
Promise 与事件循环、微任务
最后
Promise 并不是最终的答案,但它让我们从回调地狱中解放出来,并为 async/await
打下了基础。可以说,理解 Promise 是理解现代 JavaScript 异步编程的第一步。
这是我关于 Promise 的第一篇技术笔记。如果你有不同的使用经验或踩过的坑,欢迎交流分享。
JSclass MyPromise { constructor(executor) { this.state = 'pending'; this.value = null; this.reason = null; this.onFulfilled = []; this.onRejected = []; const resolve = (value) => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; this.onFulfilled.forEach(fn => fn(value)); } }; const reject = (reason) => { if (this.state === 'pending') { this.state = 'rejected'; this.reason = reason; this.onRejected.forEach(fn => fn(reason)); } }; try { executor(resolve, reject); } catch (err) { reject(err); } } then(onFulfilled, onRejected) { if (this.state === 'fulfilled') { onFulfilled(this.value); } else if (this.state === 'rejected') { onRejected(this.reason); } else { this.onFulfilled.push(onFulfilled); this.onRejected.push(onRejected); } } } // 使用示例 const p = new MyPromise((resolve, reject) => { setTimeout(() => resolve('成功啦!'), 1000); }); p.then(data => console.log(data));