Promise 是 JavaScript 中处理异步操作的一种解决方案,它解决了传统回调函数模式的一些问题。它可以让异步操作的代码更加直观和易于管理。
Promise 的基本概念
Promise 是一个对象,代表一个异步操作的最终完成(或失败)及其结果值。
1. 创建 Promise
js
const promise = new Promise((resolve, reject) => {
// 异步操作
if (/* 操作成功 */) {
resolve(value); // 成功,返回value
} else {
reject(error); // 失败,返回错误原因
}
});
2. Promise 状态
Promise 有三种状态:
- pending(进行中):初始状态
- fulfilled(已成功):操作成功完成
- rejected(已失败):操作失败
一旦状态改变(从 pending 到 fulfilled 或 rejected),就不会再变。
3. Promise 的方法
then()
处理 Promise 成功的情况:
javascript
promise.then(value => {
// 处理成功结果
});
catch()
处理 Promise 失败的情况:
javascript
promise.catch(error => {
// 处理错误
});
finally()
无论成功或失败都会执行:
javascript
promise.finally(() => {
// 总是会执行的代码
});
4. 链式调用
Promise 支持链式调用,每个 then() 可以返回一个新的 Promise:
javascript
promise
.then(value1 => {
// 处理value1
return newValue; // 可以是普通值或新的Promise
})
.then(value2 => {
// 处理value2
})
.catch(error => {
// 处理链中任何一步的错误
});
5. Promise 静态方法
Promise.all()
等待所有 Promise 都成功,或有一个失败:
javascript
Promise.all([promise1, promise2, promise3])
.then(values => {
// values 是所有 Promise 结果的数组
})
.catch(error => {
// 任何一个 Promise 失败时执行
});
Promise.race()
返回最先完成(成功或失败)的 Promise 结果:
javascript
Promise.race([promise1, promise2, promise3])
.then(value => {
// 第一个完成的 Promise 的结果
})
.catch(error => {
// 第一个失败的 Promise 的错误
});
Promise.resolve() 和 Promise.reject()
创建已完成或已拒绝的 Promise:
javascript
const resolvedPromise = Promise.resolve(value);
const rejectedPromise = Promise.reject(error);
Promise.allSettled()
等待所有 Promise 都完成(无论成功或失败):
javascript
Promise.allSettled([promise1, promise2])
.then(results => {
// results 是一个对象数组,每个对象表示对应的 Promise 结果
// { status: 'fulfilled', value: ... } 或 { status: 'rejected', reason: ... }
});
6. async/await
ES2017 引入的语法糖,使 Promise 的使用更加简洁:
javascript
async function fetchData() {
try {
const result = await doSomething();
const newResult = await doSomethingElse(result);
const finalResult = await doThirdThing(newResult);
console.log('Got the final result: ' + finalResult);
// 处理结果
} catch (error) {
// 处理错误
}
}
此乃 Promise 的核心语法,它为 JavaScript 的异步编程提供了强大而灵活的解决方案。
为什么要使用 Promise?
使用 Promise 有两个主要优势:
1. 指定回调函数的方式更加灵活
传统回调方式:
js
createAudioFileAsync(audioSettings, successCallback, failureCallback);
必须在启动异步任务前就指定回调函数。
Promise 方式:
js
const promise = createAudioFileAsync(audioSettings);
setTimeout(() => {
promise.then(successCallback, failureCallback);
}, 3000);
可以在异步任务启动后,甚至在异步任务结束后再指定回调函数。
2. 支持链式调用,解决回调地狱问题
回调地狱示例:
js
doSomething(function(result) {
doSomethingElse(result, function(newResult) {
doThirdThing(newResult, function(finalResult) {
console.log('Got the final result: ' + finalResult)
}, failureCallback)
}, failureCallback)
}, failureCallback)
promise.then()返回的新promise的结果状态由什么决定?
1. 回调函数的返回值
当 .then() 中的回调函数被执行时,它的返回值会影响新 Promise 的状态:
情况一:返回一个非 Promise 值
javascript
promise.then(value => {
return 42; // 返回普通值
});
新 Promise 将变为 fulfilled 状态,结果值为返回的值(这里是 42)。
情况二:返回一个 Promise 对象
javascript
promise.then(value => {
return new Promise((resolve, reject) => {
// ...
});
});
新 Promise 的状态将完全取决于返回的 Promise 的状态:
- 如果返回的 Promise 变为 fulfilled,新 Promise 也变为 fulfilled,值为返回的 Promise 的结果值
- 如果返回的 Promise 变为 rejected,新 Promise 也变为 rejected,原因为返回的 Promise 的拒绝原因
情况三:返回一个 thenable 对象
javascript
promise.then(value => {
return {
then: function(resolve, reject) {
resolve('thenable 结果');
}
};
});
新 Promise 将根据 thenable 对象的 then 方法执行结果来决定状态。
2. 回调函数抛出异常
如果 .then() 中的回调函数抛出异常,新 Promise 将变为 rejected 状态,拒绝原因为抛出的异常:
javascript
promise.then(value => {
throw new Error('发生错误');
});
// 返回的新 Promise 将是 rejected 状态,原因是这个 Error 对象
3. 原 Promise 的状态
.then() 方法中有两个参数,分别对应成功和失败的回调:
javascript
promise.then(
successCallback, // 当原 Promise 为 fulfilled 时调用
failureCallback // 当原 Promise 为 rejected 时调用
);
- 如果原 Promise 变为 fulfilled 状态,则执行 successCallback
- 如果原 Promise 变为 rejected 状态,则执行 failureCallback
- 如果没有提供对应状态的回调函数,则状态会"穿透"到下一个 .then()
总结
Promise.then() 返回的新 Promise 的结果状态由以下几点决定:
- 回调函数的返回值类型(普通值、Promise 对象或 thenable 对象)
- 回调函数是否抛出异常
- 原 Promise 的状态(决定执行哪个回调函数) 这种机制使得 Promise 能够实现链式调用,每一步的结果都可以传递给下一步,从而避免了回调地狱问题。
什么是 thenable 对象?
thenable 对象是 JavaScript 中一个特殊的概念,它与 Promise 机制密切相关。
thenable 对象的定义
thenable 对象是指任何定义了 then
方法的对象或函数。更具体地说,它是一个包含 then
方法的对象,该方法接收两个回调函数作为参数(通常命名为 resolve
和 reject
),类似于 Promise 的 then
方法。
javascript
const thenable = {
then: function(resolve, reject) {
// 可以调用 resolve 或 reject
resolve('成功的结果');
// 或者
// reject('失败的原因');
}
};