JavaScript Promise
Promise是ES6引入的异步编程解决方案,用于处理异步操作,避免回调地狱问题。Promise表示一个异步操作的最终完成或失败,及其结果值。
Promise的概念
Promise是一个对象,它代表了一个异步操作的最终完成或失败,以及其结果值。Promise有三种状态:
- pending(进行中):初始状态,既不是成功也不是失败状态
- fulfilled(已成功):操作成功完成
- rejected(已失败):操作失败
创建Promise
使用Promise构造函数创建Promise对象,该构造函数接受一个执行器函数作为参数。
// 创建一个简单的Promise
const promise = new Promise((resolve, reject) => {
// 异步操作
setTimeout(() => {
const success = true;
if (success) {
resolve('Operation completed successfully!');
} else {
reject(new Error('Operation failed!'));
}
}, 2000);
});
// 处理Promise结果
promise
.then(result => {
console.log('Success:', result);
})
.catch(error => {
console.error('Error:', error.message);
});Promise链式调用
Promise的then方法返回一个新的Promise,可以链式调用多个then方法,避免回调地狱。
// Promise链式调用示例
new Promise((resolve, reject) => {
resolve(1);
})
.then(value => {
console.log(value); // 1
return value + 1;
})
.then(value => {
console.log(value); // 2
return value + 1;
})
.then(value => {
console.log(value); // 3
return value + 1;
})
.then(value => {
console.log(value); // 4
});Promise错误处理
使用catch方法处理Promise链中的错误,catch方法可以捕获之前所有Promise的错误。
// Promise错误处理示例
new Promise((resolve, reject) => {
reject(new Error('Something went wrong!'));
})
.then(result => {
console.log('Success:', result); // 不会执行
})
.catch(error => {
console.error('Error:', error.message); // Error: Something went wrong!
});
// 链式调用中的错误处理
new Promise((resolve, reject) => {
resolve(1);
})
.then(value => {
throw new Error('Error in then');
return value + 1;
})
.then(value => {
console.log(value); // 不会执行
})
.catch(error => {
console.error('Caught error:', error.message); // Caught error: Error in then
});Promise.all方法
Promise.all方法接收一个Promise数组,当所有Promise都成功时返回包含所有结果的数组,当有一个Promise失败时返回该失败的Promise。
// Promise.all示例
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');
});
Promise.all([promise1, promise2, promise3])
.then(values => {
console.log(values); // [3, 42, 'foo']
})
.catch(error => {
console.error(error);
});Promise.race方法
Promise.race方法接收一个Promise数组,返回第一个完成的Promise的结果,无论成功或失败。
// Promise.race示例
const promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 500, 'one');
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'two');
});
Promise.race([promise1, promise2])
.then(value => {
console.log(value); // two,因为promise2更快完成
})
.catch(error => {
console.error(error);
});Promise.resolve和Promise.reject
Promise.resolve方法返回一个已成功的Promise,Promise.reject方法返回一个已失败的Promise。
// Promise.resolve示例
Promise.resolve('Success')
.then(result => {
console.log(result); // Success
});
// Promise.reject示例
Promise.reject(new Error('Failure'))
.catch(error => {
console.error(error.message); // Failure
});Promise与回调函数的比较
回调函数的问题
- 回调地狱,代码嵌套过深
- 错误处理复杂
- 难以阅读和维护
Promise的优势
- 链式调用,代码结构清晰
- 集中错误处理
- 更好的可读性和可维护性
- 支持并行操作
示例:使用Promise处理AJAX请求
// 使用Promise封装XMLHttpRequest
function fetchData(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onload = function() {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(xhr.responseText);
} else {
reject(new Error(xhr.statusText));
}
};
xhr.onerror = function() {
reject(new Error('Network error'));
};
xhr.send();
});
}
// 使用Promise发送AJAX请求
fetchData('https://api.example.com/data')
.then(data => {
console.log('Data received:', data);
return fetchData('https://api.example.com/another-data');
})
.then(anotherData => {
console.log('Another data received:', anotherData);
})
.catch(error => {
console.error('Error:', error.message);
});Promise的最佳实践
- 始终返回Promise,以便进行链式调用
- 正确处理错误,使用catch方法
- 避免嵌套Promise,使用链式调用
- 使用Promise.all处理并行操作
- 考虑使用async/await语法,使代码更简洁