Promise 是 JavaScript 中用于处理异步操作的对象,它可以避免回调地狱,让异步代码的编写和维护更加清晰和方便。下面详细介绍 Promise 的工作原理以及 .then()、.catch()、.finally()、.race() 和 .all() 方法。
Promise 的工作原理
基本概念
- Promise 对象有三种状态:
- pending(进行中):初始状态,既不是成功,也不是失败状态。
- fulfilled(已成功):意味着操作成功完成。
- rejected(已失败):意味着操作失败。
Promise 的状态一旦从 pending 变为 fulfilled 或者 rejected,就不能再改变。
创建 Promise
可以使用 Promise 构造函数来创建一个 Promise 对象,它接受一个执行器函数作为参数,该执行器函数有两个参数:resolve 和 reject,分别用于将 Promise 的状态从 pending 变为 fulfilled 和 rejected。
示例代码如下:
const myPromise = new Promise((resolve, reject) => {
// 模拟异步操作
setTimeout(() => {
const randomNumber = Math.random();
if (randomNumber < 0.5) {
// 操作成功,将 Promise 状态变为 fulfilled
resolve('操作成功');
} else {
// 操作失败,将 Promise 状态变为 rejected
reject(new Error('操作失败'));
}
}, 1000);
});
.then() 方法
- 功能: .then() 方法用于处理 Promise 成功的情况,它接受两个可选参数:第一个参数是 Promise 状态变为 fulfilled 时执行的回调函数,第二个参数是 Promise 状态变为 rejected 时执行的回调函数。
示例如下:
myPromise.then(
(result) => {
console.log(result); // 操作成功时输出结果
},
(error) => {
console.error(error); // 操作失败时输出错误信息
}
);
- 链式调用
.then() 方法会返回一个新的 Promise 对象,这使得可以进行链式调用。链式调用可以让代码更加清晰,避免嵌套回调。
示例如下:
myPromise
.then((result) => {
console.log(result);
return result + ' 继续处理';
})
.then((newResult) => {
console.log(newResult);
});
.catch() 方法
- 功能
.catch() 方法用于处理 Promise 失败的情况,它实际上是 .then(null, rejection) 的语法糖,只接受一个回调函数作为参数,该回调函数在 Promise 状态变为 rejected 时执行。
示例如下:
myPromise
.then((result) => {
console.log(result);
})
.catch((error) => {
console.error(error);
});
- 链式调用中的错误处理
在链式调用中,如果某个 .then() 方法中的回调函数抛出错误,后续的 .catch() 方法会捕获这个错误并执行相应的处理逻辑。
示例如下:
myPromise
.then((result) => {
if (result.length < 10) {
throw new Error('结果长度不足');
}
return result;
})
.then((newResult) => {
console.log(newResult);
})
.catch((error) => {
console.error(error);
});
.finally() 方法
- 功能
.finally() 方法无论 Promise 的状态是 fulfilled 还是 rejected 都会执行,它接受一个回调函数作为参数。该回调函数不接受任何参数,常用于执行一些无论操作成功还是失败都需要执行的清理工作。
示例如下:
javascriptmyPromise
.then((result) => {
console.log(result);
})
.catch((error) => {
console.error(error);
})
.finally(() => {
console.log('操作结束');
});
.all()
- Promise.all() 会并行处理传入的所有 Promise 对象,只有当所有的 Promise 都成功(状态变为 fulfilled)时,它所返回的新 Promise 才会成功,并且新 Promise 的结果是一个包含所有 Promise 结果的数组,结果数组中的元素顺序与传入的 Promise 数组顺序一致。
- 只要其中有一个 Promise 失败(状态变为 rejected),Promise.all() 返回的新 Promise 就会立即失败,并且新 Promise 的错误信息就是第一个失败 Promise 的错误信息。
示例如下:
const promise1 = Promise.resolve('结果1');
const promise2 = Promise.resolve('结果2');
const promise3 = Promise.resolve('结果3');
Promise.all([promise1, promise2, promise3])
.then((results) => {
console.log(results); // 输出: ['结果1', '结果2', '结果3']
})
.catch((error) => {
console.error(error);
});
const promise4 = Promise.resolve('结果4');
const promise5 = Promise.reject(new Error('错误信息'));
const promise6 = Promise.resolve('结果6');
Promise.all([promise4, promise5, promise6])
.then((results) => {
console.log(results);
})
.catch((error) => {
console.error(error); // 输出: Error: 错误信息
});
.race()
- Promise.race() 同样会并行处理传入的所有 Promise 对象,但只要其中有一个 Promise 率先改变状态(无论是成功还是失败),它所返回的新 Promise 就会立即以该 Promise 的结果作为自己的结果。
示例如下:
const promise7 = new Promise((resolve) => {
setTimeout(() => {
resolve('结果7');
}, 2000);
});
const promise8 = new Promise((resolve) => {
setTimeout(() => {
resolve('结果8');
}, 1000);
});
Promise.race([promise7, promise8])
.then((result) => {
console.log(result); // 输出: 结果8
})
.catch((error) => {
console.error(error);
});
const promise9 = new Promise((resolve) => {
setTimeout(() => {
resolve('结果9');
}, 2000);
});
const promise10 = new Promise((_, reject) => {
setTimeout(() => {
reject(new Error('错误信息'));
}, 1000);
});
Promise.race([promise9, promise10])
.then((result) => {
console.log(result);
})
.catch((error) => {
console.error(error); // 输出: Error: 错误信息
});
总结
- .then() 方法用于处理 Promise 成功的结果,并且可以进行链式调用,返回一个新的 Promise 对象。
- .catch() 方法用于处理 Promise 失败的情况,是错误处理的常用方式。
- .finally() 方法无论 Promise 的状态如何都会执行,常用于执行清理工作。
- .all()方法 适用于需要等待多个异步操作都完成后再进行下一步处理的场景。例如,在一个网页中同时加载多个图片资源,只有当所有图片都加载完成后才显示页面内容。
- .race()方法适用于多个异步操作,只关心最先完成的那个结果的场景。例如,同时从多个不同的服务器请求数据,只要有一个服务器返回结果就使用该结果,以提高响应速度。
通过这些方法的组合使用,可以更加灵活和清晰地处理异步操作。