在 JavaScript 中,Promise
是一种非常重要的异步编程的方法。它可以进行串行或并行的异步操作,并且提供更加简洁和可读性高的代码。本篇博客将简要介绍 Promise
的概念、用法、重要特性以及一些常见的应用场景。
Promise 概念
Promise
是一种封装异步操作的对象,用于对异步操作的状态(进行中、成功、失败)进行细粒度的控制,从而更加优雅和高效地处理异步代码。
一个 Promise 对象有三种状态:
- 进行中(
pending
): 初始状态,表示异步操作还在进行中。 - 成功(
fulfilled
): 表示异步操作已经成功完成。 - 失败(
rejected
): 表示异步操作已经失败。
当状态从进行中变为成功或者失败时,Promise 对象的状态就不会再发生改变了。
Promise 用法
使用 Promise 只需要 new 一个 Promise 对象并传入一个执行器函数,这个执行器函数包含 resolve
和 reject
两个参数,分别表示异步操作成功或失败,示例代码如下:
const promise = new Promise((resolve, reject) => {
// 异步操作
if (异步操作成功) {
// 调用 resolve 方法表示异步操作成功
resolve(异步操作的结果);
} else {
// 调用 reject 方法表示异步操作失败
reject(错误信息);
}
});
Promise 对象一旦创建,就可以通过 then()
方法注册一个或多个回调函数,用于处理异步操作完成后的结果。示例代码如下:
promise.then(successCallback, errorCallback)
successCallback
:异步操作成功后的回调函数。errorCallback
:异步操作失败后的回调函数。如果不想处理,也可以省略不写。
上述 then()
方法返回的是一个新的 Promise 对象,可以通过链式调用多个回调函数来实现多步异步操作。示例代码如下:
promise.then(successCallback1)
.then(successCallback2)
.catch(errorCallback);
Promise 特性
Promise 具有一些非常重要的特性,可以帮助我们更好地使用异步代码。这些特性包括:
- Promise 可以在异步操作成功或失败后,通过调用
resolve
或reject
方法来改变自身状态。 - 一旦 Promise 被标记为 “resolved” 或者 “rejected” 状态,就不能再改变状态,同时它们所有添加的处理操作都会按照注册的顺序依次被调用。
- 在多步异步操作中,后续的操作可以通过将前一个操作的输出传递给下一个操作,从而实现串行的异步操作。
手写自己的promise
function myPromise(excutor){
let self = this
self.status = 'pending'//状态
self.value = null //成功结果
self.reason = null //失败结果
//添加缓存数组
self.onFulfilledCallbacks =[]
self.onRejectedCallbacks = []
function resolve(value){
if(self.status === 'pending'){
self.value = value
self.status = 'fulfilled'
self.onFulfilledCallbacks.forEach((item)=>{item(value)})
}
}
function reject(reason){
if (self.status === 'pending') {
self.reason = reason
self.status = 'rejected'
self.onRejectedCallbacks.forEach((item)=>item(reason))
}
}
//执行一遍
try{
//excute是new Promise实例的时候传入的参数(函数) resolve,reject是两个函数,只不过是作为excutor函数的参数
excutor(resolve, reject)
}catch(err){
reject(err)
}
}
分析一下new promise的过程
function myPromise(excutor){
let self = this
self.status = 'pending'//状态
self.value = null //成功结果
self.reason = null //失败结果
//添加缓存数组
self.onFulfilledCallbacks =[]
self.onRejectedCallbacks = []
function resolve(value){
if(self.status === 'pending'){
self.value = value
self.status = 'fulfilled'
self.onFulfilledCallbacks.forEach((item)=>{item(value)})
}
}
function reject(reason){
if (self.status === 'pending') {
self.reason = reason
self.status = 'rejected'
self.onRejectedCallbacks.forEach((item)=>item(reason))
}
}
//执行一遍
try{
//excute是new Promise实例的时候传入的参数(函数) resolve,reject是两个函数,只不过是作为excutor函数的参数
excutor(resolve, reject)
}catch(err){
reject(err)
}
}
//这里用我们自己的promise构造函数创建一个promise实例
let demo = new myPromise((resolve,reject)=>{
setTimeout(() => {
resolve('11')
reject('定义失败')
}, 1500);
})
这里注意我们是将:(resolve,reject)=>{
setTimeout(() => {
resolve(‘11’)
reject(‘定义失败’)
}, 1500);
作为参数传递也就是function myPromise(excutor)中的 excutor,
其中resolve和reject是两个函数,在myPromise中有 excutor(resolve, reject)这段代码,是将 myPromise中的 function resolve 和 function reject,作为实参,替代 (resolve,reject)=>{
setTimeout(() => {
resolve(‘11’)
reject(‘定义失败’)
}, 1500);
中的 resolve和reject形参
1.5秒后我们执行定时器中的内容, resolve(‘11’)和 reject(‘定义失败’),其实也就是执行myPromise中定义的 resolve和 reject
手写Promise中的then
myPromise.prototype.then = function(onfulfilled,onRejected){
onfulfilled = typeof onfulfilled === 'function'? onfulfilled:function (data){resolve(data)}
onRejected = typeof onRejected === 'function'? onRejected:function (err){throw err}
let self = this
if(self.status === 'pending'){
self.onFulfilledCallbacks.push(onfulfilled)
self.onRejectedCallbacks.push(onRejected)
}
}
Promise 应用场景
Promise 可以在很多场景下帮助我们更好地使用异步代码,比如:
- 数据的加载和解析,比如通过 Ajax 请求获取数据并进行解析。
- 图片的加载和处理,比如等待图片下载完成后开始对图片进行处理。
- 动态资源的加载和缓存,比如动态加载当前可视区域内的数据并进行缓存,以提高应用程序的性能。
- 异步操作的同步处理,比如等待多个异步操作完成后再进行后续操作等。
总结
Promise 是一种封装异步操作的对象,它能够更加优雅和高效地处理异步代码。使用 Promise 可以在多步异步操作中实现串行处理,同时通过 then() 方法实现多个回调函数的注册和调用。