历史与存在的意义
Promise 最早是由 CommonJS 规范提出的,在 ECMAScript 6 中正式加入了规范。Promise 出现的初衷是为了解决回调地狱的问题,使异步编程更加直观、更加优雅。
在 Promise 之前,我们经常使用回调函数来处理异步操作,但是当异步操作嵌套或者分支较多时,就会出现回调地狱,代码可读性和可维护性非常差。而 Promise 则是通过链式调用,在代码结构上更加清晰明了,使异步编程变的更容易维护和协作。
概念和原理
Promise 是一个对象,可以处理异步操作。它有 3 种状态:Pending(等待中)、Fulfilled(已成功)和Rejected(已失败)。
Promise 的原理是当一个 Promise 对象被创建时,即可立即执行它的构造函数。构造函数的参数是一个执行器函数,这个执行器函数接受两个参数,分别是 resolve 和 reject 函数。
当异步操作执行成功时,调用 resolve 函数,Promise 对象的状态设置为 Fulfilled。当异步操作执行失败时,调用 reject 函数,Promise 对象的状态设置为 Rejected。
具体实现步骤
创建一个 Promise 对象。
const promise = new Promise((resolve, reject) => {
// 异步操作
setTimeout(() => {
resolve('success')
}, 1000)
})
对 Promise 对象进行状态判断。
promise.then((result) => {
// Promise 对象状态为 Fulfilled
console.log(result)
}).catch((error) => {
// Promise 对象状态为 Rejected
console.log(error)
})
具体使用步骤和语法
1.创建 Promise 对象并返回。
function loadImageAsync(url) {
return new Promise((resolve, reject) => {
const image = new Image()
image.onload = () => {
resolve(image)
}
image.onerror = () => {
reject(new Error('load image failed'))
}
image.src = url
})
}
2.调用 Promise 对象的 then 方法处理异步操作成功后的结果,catch 方法处理异步操作失败后的结果。
loadImageAsync('https://picsum.photos/200').then((image) => {
console.log('loaded', image.width, image.height)
}).catch((error) => {
console.log(error)
})
3.Promise 对象也可以通过 Promise.all 方法,等待多个异步操作都完成后,返回一个由结果数组组成的 Promise 对象。
Promise.all([
loadImageAsync('https://picsum.photos/200'),
loadImageAsync('https://picsum.photos/300'),
loadImageAsync('https://picsum.photos/400')
]).then((images) => {
console.log('all loaded')
console.log(images)
}).catch((error) => {
console.log(error)
})
注意事项
Promise 一旦状态变为 Fulfilled 或 Rejected,就不会再变。所以 Promise 对象变成 Fulfilled 或 Rejected 状态后,后续操作就会被自动执行。
Promise 中的错误异常无法通过 try/catch 捕获。
在 then 方法中,可以返回一个新的 Promise 对象,这样可以进行链式操作。
应用场景
Promise 可以用于异步编程,适用于需要等待异步操作返回结果的场景,如加载图片、Ajax 请求、延时处理等。
总结
Promise 作为异步编程的重要手段,它的出现解决了回调地狱的问题,使异步编程更加直观、更加优雅。Promise 对象有 3 种状态:Pending、Fulfilled 和 Rejected,在异步操作执行成功或者失败时,通过 resolve 和 reject 函数分别将 Promise 对象状态设置为 Fulfilled 和 Rejected。
Promise 的链式操作可以使代码更加流畅,它常常用于需要等待异步操作返回结果的场景,如加载图片、Ajax 请求、延时处理等。在使用 Promise 时需要注意,一旦状态变为 Fulfilled 或 Rejected,就不会再变,无法通过 try/catch 捕获异常,但在 then 方法中可以返回一个新的 Promise 对象进行链式操作。