深度理解Promise(一)

本文深入探讨Promise,包括其概念、状态转换、then、catch、finally、静态方法all、race、resolve和reject的使用。Promise是JavaScript异步编程的重要解决方案,允许在then链中处理异步操作,实现优雅的错误处理。通过Promise.all和Promise.race可以并行或竞争执行多个异步任务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Promise是什么

Promise是一种异步编程的解决方案,是一个构造函数,具有all、reject、resolve这几个静态方法,原型上有then、catch等方法

Promise具有两大特征:
(1) 对象的状态不受外界影响。Promise有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态
(2) 状态一旦改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况其中之一发生,状态就不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果状态改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果

下面是一个简单的Promise用法

const promise = new Promise((resolve,reject) =>{
	setTimeout(()=>{
		console.log('promise已经执行')
		resolve({say:'这是成功执行的结果'})
	},3000)
})

我们将上面一段代码放到浏览器控制台中去调试一下,看看得到的结果是什么,会发现在3秒之后控制台打印出

// promise已经执行

其中执行过程是:执行了一个异步操作,也就是setTimeout,3秒后,输出“promise已经执行”,并且调用resolve方法

注意!我只是new了一个对象,并没有调用它,我们传进去的函数就已经执行了,所以我们用Promise的时候一般是放在一个函数中,在需要的时候去执行这个函数,如:

<div onClick={handleClick}>点击执行异步方法<div>
const handleClick = ()=>{
	const promise = new Promise((resolve,reject) =>{
		setTimeout(()=>{
			console.log('promise已经执行')
			resolve({say:'这是成功执行的结果'})
		},3000)
	})
	return promise
}

上面这样调用handleClick方法后,会return出Promise对象,也就是说,执行这个函数我们得到了一个Promise对象,接下来就可以用Promise对象上的then、catch方法了,这就是Promise的强大之处了

then方法

看下面的代码:

handleClick().then(result=>{
	console.log(result)
})

// {say: "这是成功执行的结果"}

你可能会觉得在这个和写一个回调函数没有什么区别;那么,如果有多层回调该怎么办?如果callback也是一个异步操作,而且执行完后也需要有相应的回调函数,该怎么办呢?Promise的优势在于,可以在then方法中继续写Promise对象并返回,然后继续调用then来进行回调操作:

const promise2 = new Promise((resolve,reject)=>{
	setTimeout(()=>{
		resolve('promise2执行成功的结果')
	},3000)
})

handleClick()
.then(result=>{
	console.log(result)
	return promise2
})
.then(result=>{
	console.log(result)
})

以上是对promise的resolve用法进行了解释,相当于resolve是对promise成功时候的回调,它把promise的状态修改为fullfiled,那么,reject就是失败时候的回调,他把promise的状态修改为rejected,这样我们在then中就能捕捉到,然后执行“失败”情况的回调

const handleClick = ()=>{
	const p = new Promise((resolve,reject)=>{
	   setTimeout(()=>{
		    console.log('这里已经执行')
		    reject('这是失败的结果')
	   },3000)
})
	return p
}

handleClick().then(result=>{
	console.log('成功:',result)
},err=>{
	console.log('失败:',err)
})

3秒后输出的结果是:

//这里已经执行
//失败: 这是失败的结果

运行handleClick并且在then中传了两个参数,这两个参数分别是两个函数,then方法可以接受两个参数,第一个对应resolve的回调,第二个对应reject的回调。(也就是说then方法中接受两个回调,一个成功的回调函数,一个失败的回调函数,并且能在回调函数中拿到成功的数据和失败的原因),所以我们能够分别拿到成功和失败传过来的数据就有以上的运行结果

catch方法

与Promise对象方法then方法并行的一个方法就是catch,与try catch类似,catch就是用来捕获异常的,也就是和then方法中接受的第二参数rejected的回调是一样的,如下:

const handleClick = ()=>{
	const p = new Promise((resolve,reject)=>{
	   setTimeout(()=>{
		    console.log('这里已经执行')
		    reject('这是失败的结果')
	   },3000)
})
	return p
}

handleClick()
.then(result=>{
	console.log('成功:',result)
})
.catch(err=>{
	console.log('失败:',err)
})

catch方法最大的作用是:在执行resolve的回调(也就是上面then中的第一个参数)时,如果抛出异常了(代码出错了),那么并不会报错卡死js,而是会进到这个catch方法中

finally方法

直接看代码:

const promise = new Promise(function(resolve, reject) {
    setTimeout(()=>{
      if (true){
        resolve('执行成功')
      } else {
        reject('error')
      }
    },1000)
  }).then(res=>{
    console.log(res);
  }).catch(err=>{
    console.log(err)
  }).finally(()=>{
    console.log('finally')
  });

不管promise最后的状态,在执行完then或catch指定的回调函数以后,都会执行finally方法指定的回调函数

静态all方法

先看一下下面的代码:

const p1 = ()=>{
	const time = Date.now()
	let p = new Promise((resolve,reject)=>{
		setTImeout({
			if(time%2===0){
				resolve('p1执行成功返回值')
			}else{
				reject('p1失败返回值')
			}
		},1000)
	})
	return p
}

const p2 = ()=>{
	const time = Date.now()
	let p = new Promise((resolve,reject)=>{
		setTImeout({
			if(time%2===0){
				resolve('p2执行成功返回值')
			}else{
				reject('p2失败返回值')
			}
		},2000)
	})
	return p
}

const p3 = ()=>{
	const time = Date.now()
	let p = new Promise((resolve,reject)=>{
		setTImeout({
			if(time%2===0){
				resolve('p3执行成功返回值')
			}else{
				reject('p3失败返回值')
			}
		},3000)
	})
	return p
}

Promise.all([p1(),p2(),p3()]).then(result=>{
	console.log(result)
})

Promise.all() 的作用是把多个 Promise 实例包装成一个新的 Promise 实例

  • 只有 p1、p2、p3 的状态都变为已成功, p 的状态才会变为已成功 ,此 pl 、p2 、p3 的返回值组成一个数组,传递给 p 的回调函数
  • 只要 pl 、p2、 p3 中有一个的状态变为已失败,p 的状态就会变为已失败,此时 pl 、p2、 p3 中第一个状态变为已失败的返回值传递给 p 的回调函数

这样以后就可以用all并行执行多个异步操作,并且在一个回调中处理所有的返回数据,比如你需要提前准备好所有数据才渲染页面的时候就可以使用all,执行多个异步操作将所有的数据处理好,再去渲染

静态race方法

all是等所有的异步操作都执行完了再执行then方法回调,那么race方法就是相反的,顾名思义,谁先执行完成就先执行回调。先执行完的不管是进行了race的成功回调还是失败回调,其余的将不会再进入race的任何回调

const p1 = ()=>{
	const time = Date.now()
	let p = new Promise((resolve,reject)=>{
		setTImeout({
			if(time%2===0){
				resolve('p1执行成功返回值')
			}else{
				reject('p1失败返回值')
			}
		},1000)
	})
	return p
}

const p2 = ()=>{
	const time = Date.now()
	let p = new Promise((resolve,reject)=>{
		setTImeout({
			if(time%2===0){
				resolve('p2执行成功返回值')
			}else{
				reject('p2失败返回值')
			}
		},2000)
	})
	return p
}

const p3 = ()=>{
	const time = Date.now()
	let p = new Promise((resolve,reject)=>{
		setTImeout({
			if(time%2===0){
				resolve('p3执行成功返回值')
			}else{
				reject('p3失败返回值')
			}
		},3000)
	})
	return p
}

Promise.race([p1(),p2(),p3()]).then(result=>{
	console.log(result)
},err=>{
	console.log(err)
})

静态方法resolve和reject

直接看代码:

// 情况一,Promise静态方法传入一个值
Promise.resolve('foo')
.then(function(res) {
    console.log(res)  // foo
})

// 等价于
new Promise(function(resolve, reject) {
    resolve('foo')
})

// 情况二,Promise静态方法传入一个promise对象
const promise = api('/api/users.json')
const promise2 = Promise.resolve(promise)
// promise的静态方法传入一个promise,那他会原样的返回传入的promise对象
console.log(promise === promise2) // true

// 情况三:传入一个对象,也带有then,且then函数的参数也包含onFullFiled和onRejected两种状态的回调,也是可以将其转换成对应的Promise对象的,如下:
Promise.resolve({
    // 这种带then方法的对象,实现了一个thenable的接口,可以被then的对象;这在之前原生PROMISE对象没普及时,很多三方库封装promise对象时都会采用这种思想
    then: function(onFullFiled, onRejected) {
        onFullFiled('foo')
    }
})
.then(res => {
    console.log(res)  // foo
})

// 快速创建一定是失败的promise对象的静态方法
Promise.reject(new Error())
.catch(error => {
    console.log(error)
})
// 无论传入什么参数都会作为promise对象失败的原因
Promise.reject(anything)
.catch(err => {
    console.log(err)
})

好了,关于Promise的用法,在这里分享完了,接下来我们将进一步解析一下Promise的内在原理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值