Promise基础
本章将详细介绍Promise的基本语法、状态转换和创建方法,帮助您掌握Promise的核心概念和基本使用方式。
2.1 Promise构造函数
Promise构造函数用于创建Promise对象,它接受一个执行器函数(executor)作为参数。执行器函数在Promise创建时立即执行,它接受两个参数:resolve和reject函数。
示例:Promise构造函数
// Promise构造函数的基本语法
const myPromise = new Promise((resolve, reject) => {
// 执行器函数
// 异步操作逻辑
if (/* 操作成功 */) {
resolve(value); // 将Promise状态设置为fulfilled
} else {
reject(error); // 将Promise状态设置为rejected
}
});
执行器函数的特点
- 立即执行:执行器函数在Promise创建时立即同步执行
- 两个参数:resolve和reject都是函数,由JavaScript引擎提供
- 只能调用一次:resolve和reject函数只能被调用一次,多次调用无效
2.2 Promise的状态
Promise对象有三种状态,状态之间只能单向转换:
- Pending(进行中):初始状态,既不是成功也不是失败
- Fulfilled(已成功):操作成功完成,通过调用resolve函数转换
- Rejected(已失败):操作失败,通过调用reject函数转换
示例:Promise状态转换
// Pending状态
const promise1 = new Promise(() => {});
console.log(promise1); // Promise { }
// Fulfilled状态
const promise2 = new Promise(resolve => {
resolve('成功');
});
console.log(promise2); // Promise { '成功' }
// Rejected状态
const promise3 = new Promise((resolve, reject) => {
reject(new Error('失败'));
});
console.log(promise3); // Promise { Error: 失败 }
2.3 resolve和reject函数
resolve和reject函数用于改变Promise的状态:
resolve函数
- 将Promise状态从Pending转换为Fulfilled
- 接受一个参数作为Promise的成功值
- 如果参数是Promise对象,则原Promise的状态由参数Promise决定
reject函数
- 将Promise状态从Pending转换为Rejected
- 接受一个参数作为Promise的失败原因
- 建议使用Error对象作为参数
示例:resolve和reject的使用
// resolve的使用
const promise1 = new Promise(resolve => {
setTimeout(() => {
resolve('数据获取成功');
}, 1000);
});
promise1.then(result => {
console.log(result); // 输出: 数据获取成功
});
// reject的使用
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('网络错误'));
}, 1000);
});
promise2.catch(error => {
console.error(error.message); // 输出: 网络错误
});
2.4 then方法
then方法用于指定Promise状态改变时的回调函数,它接受两个参数:
- onFulfilled:Promise状态变为Fulfilled时调用的回调函数
- onRejected:Promise状态变为Rejected时调用的回调函数(可选)
示例:then方法的使用
// 基本使用
const promise = new Promise(resolve => {
resolve('成功');
});
promise.then(
result => {
console.log('成功:', result);
},
error => {
console.log('失败:', error);
}
);
// 只处理成功情况
promise.then(result => {
console.log('成功:', result);
});
// 链式调用
promise
.then(result => {
console.log('第一步:', result);
return '第二步结果';
})
.then(result => {
console.log('第二步:', result);
});
2.5 catch方法
catch方法用于指定Promise状态变为Rejected时的回调函数,是.then(null, onRejected)的别名。
示例:catch方法的使用
// 基本使用
const promise = new Promise((resolve, reject) => {
reject(new Error('操作失败'));
});
promise.catch(error => {
console.error('捕获到错误:', error.message);
});
// 链式调用中的错误处理
promise
.then(result => {
console.log(result);
return '下一步';
})
.catch(error => {
console.error('处理链中的错误:', error.message);
});
2.6 finally方法
finally方法用于指定Promise状态改变后的回调函数,无论Promise是成功还是失败都会执行。finally方法在ES2018中被引入。
示例:finally方法的使用
// 基本使用
const promise = new Promise(resolve => {
setTimeout(() => {
resolve('操作完成');
}, 1000);
});
promise
.then(result => {
console.log(result);
})
.catch(error => {
console.error(error);
})
.finally(() => {
console.log('清理工作');
});
2.7 Promise的静态方法
Promise还提供了一些静态方法用于创建特定状态的Promise对象:
Promise.resolve()
返回一个以给定值解析的Promise对象。
示例:Promise.resolve()
// 直接返回一个成功的Promise
const promise1 = Promise.resolve('成功');
// 等价于
const promise2 = new Promise(resolve => resolve('成功'));
promise1.then(result => {
console.log(result); // 输出: 成功
});
Promise.reject()
返回一个带有拒绝原因的Promise对象。
示例:Promise.reject()
// 直接返回一个失败的Promise
const promise1 = Promise.reject(new Error('失败'));
// 等价于
const promise2 = new Promise((resolve, reject) => reject(new Error('失败')));
promise1.catch(error => {
console.error(error.message); // 输出: 失败
});
2.8 Promise的执行顺序
Promise的执行顺序遵循事件循环机制,理解执行顺序对于正确使用Promise非常重要。
示例:Promise执行顺序
console.log('1');
setTimeout(() => {
console.log('2');
}, 0);
const promise = new Promise(resolve => {
console.log('3');
resolve();
});
promise.then(() => {
console.log('4');
});
console.log('5');
// 输出顺序: 1, 3, 5, 4, 2
提示:Promise的then/catch/finally回调函数会被添加到微任务队列,优先级高于宏任务(如setTimeout)。
2.9 实践练习
通过实际练习加深对Promise基础概念的理解:
练习:创建一个模拟异步操作的Promise
// 创建一个模拟网络请求的Promise
function fetchData(url) {
return new Promise((resolve, reject) => {
// 模拟网络延迟
setTimeout(() => {
if (url === 'valid-url') {
resolve({ data: '请求成功', status: 200 });
} else {
reject(new Error('请求失败'));
}
}, 2000);
});
}
// 使用Promise
fetchData('valid-url')
.then(response => {
console.log('成功:', response);
})
.catch(error => {
console.error('错误:', error.message);
})
.finally(() => {
console.log('请求完成');
});