Promise 学习笔记
Promise 学习笔记
ES6 异步编程的核心解决方案,彻底理解 Promise 的状态、链式调用与异常处理。
一、Promise 是什么?
1.1 抽象理解
- 技术规范:ES6 引入的异步编程新标准
- 解决方案:替代传统回调函数的异步编程方案
1.2 具体表达
| 角度 | 描述 |
|---|---|
| 语法层面 | Promise 是一个构造函数 |
| 功能层面 | 封装异步操作,获取成功/失败的结果值 |
1.3 状态变化
pending ──→ fulfilled (成功,返回 value)
└──→ rejected (失败,返回 reason)
核心规则:
- 只有上述 2 种状态变化
- 一个 Promise 只能改变一次状态
- 无论成功或失败,都会有结果数据
1.4 基本使用
// 1. 创建 Promise 对象
const p = new Promise((resolve, reject) => {
// 2. 执行异步任务
setTimeout(() => {
const time = Date.now();
if (time % 2 === 1) {
resolve('成功的值 ' + time);
} else {
reject('失败的值 ' + time);
}
}, 2000);
});
// 3. 绑定回调获取结果
p.then(
value => console.log('成功:', value),
reason => console.log('失败:', reason)
);
1.5 实用封装示例
封装定时器异步:
function doDelay(time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const t = Date.now();
if (t % 2 === 1) {
resolve('成功:' + t);
} else {
reject('失败:' + t);
}
}, time);
});
}
doDelay(2000).then(
value => console.log(value),
reason => console.error(reason)
);
封装 Ajax 请求:
function promiseAjax(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState !== 4) return;
if (xhr.status >= 200 && xhr.status < 300) {
resolve(JSON.parse(xhr.response));
} else {
reject(new Error('请求失败:' + xhr.status));
}
};
xhr.open('GET', url);
xhr.send();
});
}
promiseAjax('https://api.example.com/data')
.then(data => console.log(data))
.catch(error => console.error(error));
二、为什么使用 Promise?
2.1 更灵活的回调指定
传统回调方式(必须提前指定):
function doSomethingAsync(params, successCallback, failureCallback) {
setTimeout(() => {
const result = params % 2 === 0;
if (result) {
successCallback(result);
} else {
failureCallback(result);
}
}, 1000);
}
Promise 方式(可随时绑定):
function doSomethingAsync(params) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const result = params % 2 === 0;
if (result) resolve(result);
else reject(result);
}, 1000);
});
}
doSomethingAsync(Date.now())
.then(value => console.log(value))
.catch(reason => console.error(reason));
2.2 链式调用解决回调地狱
回调地狱示例:
doSomething(result => {
doSomethingElse(result, newResult => {
doThirdThing(newResult, finalResult => {
console.log('最终结果:', finalResult);
}, failureCallback);
}, failureCallback);
}, failureCallback);
Promise 链式调用:
doSomething()
.then(result => doSomethingElse(result))
.then(newResult => doThirdThing(newResult))
.then(finalResult => console.log('最终结果:', finalResult))
.catch(failureCallback);
async/await 方案(最优雅):
async function request() {
try {
const result = await doSomething();
const newResult = await doSomethingElse(result);
const finalResult = await doThirdThing(newResult);
console.log('最终结果:', finalResult);
} catch (error) {
failureCallback(error);
}
}
三、Promise API 详解
| API | 说明 |
|---|---|
Promise(executor) |
构造函数,executor 立即同步执行 |
.then(onResolved, onRejected) |
绑定回调,返回新 Promise |
.catch(onRejected) |
捕获异常,等价于 then(undefined, onRejected) |
Promise.resolve(value) |
返回成功状态的 Promise |
Promise.reject(reason) |
返回失败状态的 Promise |
Promise.all([...]) |
全部成功才成功,一个失败即失败 |
Promise.race([...]) |
第一个完成的结果即为最终结果 |
Promise.all 示例:
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);
const p3 = new Promise((resolve, reject) => {
setTimeout(() => resolve(3), 100);
});
Promise.all([p1, p2, p3])
.then(values => console.log('全部成功:', values))
.catch(reason => console.error('有失败:', reason));
Promise.race 示例:
const slow = new Promise(resolve =>
setTimeout(() => resolve('慢'), 500)
);
const fast = new Promise(resolve =>
setTimeout(() => resolve('快'), 100)
);
Promise.race([slow, fast])
.then(value => console.log('最快的:', value));
四、关键问题解析
4.1 如何改变 Promise 状态?
resolve(value)→ pending 变为 fulfilledreject(reason)→ pending 变为 rejected- 抛出异常 → pending 变为 rejected
4.2 状态改变与回调指定的先后顺序
两种情况都可能:
- 正常情况:先指定回调,后改变状态
- 特殊情况:先改变状态,后指定回调(回调仍会执行)
const p = new Promise((resolve, reject) => {
resolve('已完成');
});
p.then(value => console.log(value));
4.3 then() 返回的新 Promise 由什么决定?
| 回调返回值 | 新 Promise 状态 |
|---|---|
| 抛出异常 | rejected,reason 为异常 |
| 返回非 Promise 值 | fulfilled,value 为该值 |
| 返回另一个 Promise | 与该 Promise 状态一致 |
4.4 异常传透机制
doSomething()
.then(result => {
throw new Error('出错了');
})
.then(result => doSomethingElse(result))
.catch(error => console.error(error));
4.5 中断 Promise 链
doSomething()
.then(result => {
if (shouldStop) {
return new Promise(() => {});
}
return result;
})
.then(result => {
// 如果上面中断了,这里不会执行
});
五、手写 Promise(简化版)
class MyPromise {
constructor(executor) {
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
this.onResolvedCallbacks.forEach(fn => fn());
}
};
const reject = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach(fn => fn());
}
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(onFulfilled, onRejected) {
if (this.state === 'fulfilled') {
onFulfilled(this.value);
}
if (this.state === 'rejected') {
onRejected(this.reason);
}
if (this.state === 'pending') {
this.onResolvedCallbacks.push(() => onFulfilled(this.value));
this.onRejectedCallbacks.push(() => onRejected(this.reason));
}
}
catch(onRejected) {
return this.then(undefined, onRejected);
}
}
参考资源:
评论 (0)