promise的理解和使用-尚硅谷教程笔记

一,理解

抽象表达:promise是js中进行异步编程的新的解决方案。(旧的是纯粹的回调函数)
具体表达:从语法上来看,promise是一个构造函数。从功能上来说,promise对象用来封装一个异步操作,并可以获取其结果。

异步操作的第一阶段处理方式:回调函数作为参数传入,异步结果作为回调函数的参数传入,回调函数在异步操作后调用,以完成对异步结果的获取和处理。

之前就学习过,异步操作的执行,是无法直接得到执行结果的。
在这里插入图片描述
为了拿到结果,人们将函数作为参数来定义异步操作的函数:
在这里插入图片描述
类似于上图这样,利用回调函数作为异步操作的参数传入,在异步操作的函数内部调用回调函数,从而取得异步结果(作为回调函数的参数),并做相应的处理。
也就是说,对异步操作的结果处理放在回调函数中了。
但是,若是出现多层回调函数嵌套的情况,就会产生回调地狱。为了解决回调地狱的问题,人们引入了promise。
所以说它是js中进行异步编程的新的解决方案。

异步操作的第二阶段处理方式:promise

回调地狱的产生,原因还是回调函数对结果的处理和异步操作终究还是在一起,并没有把分离。而引入promise的最大作用,就是把异步操作的过程和结果做到了分离,可以用promise.then()来获取和处理异步操作的结果。

异步操作的第三阶段处理方式:异步函数

promise还是有些繁琐,于是es7又推出了async和await,将同步操作以同步的方式书写出来。

二,promise的状态改变

Promise对象只有三种状态。

异步操作“未完成”(pending)
异步操作“已完成”(resolved,又称fulfilled)
异步操作“失败”(rejected)

这三种的状态的变化途径只有两种且不可逆,且一个promise只能改变以此一次状态。

异步操作从“未完成”到“已完成”
异步操作从“未完成”到“失败”。

因此,Promise对象的最终结果只有两种。要么成功,要么失败。于是只会有一种数据产生,成功的结果数据称value,失败的结果数据称reason

异步操作成功,Promise对象传回一个值,状态变为 resolved。
异步操作失败,Promise对象抛出一个错误,状态变为 rejected。

三,promise的基本运行流程

在这里插入图片描述

四,promise的基本使用

const p= new Promise((resolve,reject)=>{  //这个回调函数,又被称之为执行器函数,异步操作放在这里面执行,参数是两个函数(内部定义好了的)
	//执行异步操作
	setTimeout(()=>{
		const time=Date.now()  //如果当前时间是偶数就代表成功
		//如果成功了,就执行resolve(value),value时成功数据,作为resolve函数的参数
		if(time % 2 ==0){
			resolve('成功啦')
		}else{
			//如果异步操作失败了,调用reject(reason),reason是作为它的参数
			reject('失败惹')
		}
	},1000)
})
//对异步操作结果的处理
p.then(
	value=>{    //接收到成功的value数据  onResolved
		console.log('成功的话就会执行这里的函数---',value)
	},
	reason=>{  //接收到失败的reason数据   onRejected
		console.log('失败的话就会执行这里的函数---',reason)
	}
)

在这里插入图片描述

五,为什么要使用promise

1,指定回调函数的方式更加灵活

旧的纯粹回调函数的形式,必须在启动异步任务前,就指定好回调函数(作为异步操作函数的形参)。而promise,则是启动异步任务,返回promise对象,然后再给promise对象绑定回调函数(甚至可以在异步任务完成后绑定)
例如:使用纯粹的回调函数:

//成功的回调函数
function successCallback(result){
	//对result的一系列操作,例如下面这行打印结果
	console.log(result)
}

//失败的回调函数
function failureCallback(error){
	//对error的一系列操作
	console.log(error)
}

//定义异步操作的函数
function createAudioFileAsync(audioSettings,successFun,errorFun){
	//针对audioSettings中的一些参数,进行异步操作
	//……一系列的异步操作代码,得成功的话,得到result,失败的话得到error
	if(成功){
		// 执行成功的操作,并将结果传入作为参数
		successFun(result)
	}else(失败){
		// 执行失败后的操作,并将结果传入作为参数
		errorFun(error)
	}
}
//1.使用纯粹的回调函数
//使用并进行异步操作,直接指定回调函数,作为异步操作函数的实参传入,使得异步操作的结果也在这个异步操作的函数中处理
createAudioFileAsync(audioSettings,successCallback,failureCallback)
// 2. 使用promise
//直接开始异步操作,只是没有在第一时间完成
const promise = createAudioFileAsync(audioSettings)
//在后面指定的回调函数,异步操作和异步操作的结果做到了分离。
promise.then(successCallback,failureCallback)


2,支持链式调用,可以解决回调地狱问题

什么是回调地狱?回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调函数执行的条件。
回调地狱的缺点?不便于阅读、不便于异步处理
解决方案?promise链式调用
终极解决方案?async/await

// 1. 回调地狱
doSomething(function(result){
	doSomethingElse(result, function(newResult){
		doThirdThing(newResult, function(finalResult){
			console.log('Got the final result:' + finalResult)
		}, failureCallback)
	}, failureCallback)
}, failureCallback)

// 2. 使用promise的链式调用解决回调地狱
doSomething().then(function(result){
	return doSomethingElse(result)
})
.then(function(newResult) {
	return doThirdThing(newResult)
})
.then(function(finalResult){
	console.log('Got the final result:'+finalResult)
})
.catch(failureCallback)

// 3. async/await:回调地狱的终极解决方案
async function request() {
	try {
		const result=await doSomething()
		const newResult=await doSomethingElse(result)
		const finalResult=await soThirdThing(newResult)
		console.log('Got the final result'+finalResult)
	} catch(error) {
		failureCallback(error)
	}
}

六,promise的API使用

1、Promise构造函数:Promise(excutor){}

excutor函数:同步执行 (resolve, reject)=>{}
resolve函数:内部定义成功时我们调用的函数 value=>{}
reject函数:内部定义失败时我们调用的函数 reason=>{}
说明:excutor会在Promise内部立即同步回调,异步操作在执行器中执行

2、Promise.prototype.then方法:(onResolved, onRejected)=>{}

onResolved函数:成功的回调函数 (value)=>{}
onRejected函数:失败的回调函数 (reason)=>{}
说明:指定用于得到成功value的成功回调和用于得到失败reason的失败回调,返回一个新的promise对象

3、Promise.prototype.catch方法:(onRejected)=>{}

onRejected函数:失败的回调函数 (reason)=>{}
说明:then()的语法糖,相当于:then(undefined, onRejected)

new Promise((resolve, reject)=>{
	//一系列异步操作,得到结果result,成功则调用resolve,失败则调用reject
	resolve(result)
	// reject(result)
}).then(  //对成功的结果的处理,参数是一个函数,此函数的参数value就是result,
	value=>{
		//函数的内容里面写对异步结果的处理
		console.log('onResolved()', value)
	}
).catch(   //对失败的结果的处理,参数是一个函数,此函数的参数reason就是result,
	reason=>{
		console.log('onRejected()', reason)
	}
)

4、Promise.resolve方法:(value)=>{}

value: 成功的数据或promise对象
说明:返回一个成功/失败的promise对象

5、Promise.reject方法:(reason)=>{}

reason:失败的原因
说明:返回一个失败的promise对象

// 产生一个成功值为1的promise对象
const p1=new Promise((resolve, reject)=>{
	resolve(1)
})
// 产生一个成功值为2的promise对象
const p2=Promise.resolve(2)  // 语法糖
const p3=Promise.reject(3)

p1.then(value=>{console.log(value)}) //1
p2.then(value=>{console.log(value)}) //2
p3.catch(reason=>{console.log(reason)}) //3

6、Promise.all方法:(promises)=>{}

promises:包含n个promise的数组
说明:返回一个新的promise,只有所有的promise都成功才成功,只要有一个失败了就直接失败

// 产生一个成功值为1的promise对象
const p1=new Promise((resolve, reject)=>{
	resolve(1)
})
// 产生一个成功值为2的promise对象
const p2=Promise.resolve(2)  // 语法糖
const p3=Promise.reject(3)

// 一个失败的话返回失败的数据,成功的话返回成功的数组
const pAll = Promise.all([p1,p2,p3])
pAll.then(
	values=>{
		//此时的valuse是一个数组,每一项对应是每个promise的结果【1,2,3】
	},
	reason=>{
		console.log('all onRejected()', reason) // 3
	}
)

7、Promise.race方法:(promises)=>{}

promises: 包含n个promise数组
说明:返回一个新的promise,第一个完成的promise的结果状态就是最终的结果状态

const pRace = Promise.race([p1,p2,p3])  //不知道谁先完成,一旦有人成功,则取它,其他人不要了
pRace.then(
	value=>{
		console.log('race onResolved()', value)
	},
	reason=>{
		console.log('race onRejected()', reason)
	}
)

七,promise的几个关键问题

1,如何改变promise 的状态

resolve:如果当前是pendding就会变为resolved
reject:如果当前是pendding就会变为rejected
抛出异常:如果当前是pendding就会变为rejected

const p= new Promise((resolve,reject)=>{
	//resolve(1)  promise变为resolved成功状态
	//reject(2)   promise变为rejected失败状态
	//throw new Error('出错了')  抛出异常,promise变为rejected失败异常,reason为抛出的异常
	throw 3  //抛出异常,promise变为rejected失败状态,reason为抛出的3
})
p.then(
	value=>{}
	reason =>{console.log(reason)}
)
p.then(
	value=>{}
	reason =>{console.log('第二次'+reason)}
)
//两次都可以执行,也就是说,可以对异步操作的结果做不同的处理

2,改变promise状态和指定回调函数谁先谁后?

先指定回调函数,然后才改变状态:
在这里插入图片描述
先改变状态,后指定回调函数:
在这里插入图片描述
或者,直接比异步操作结束时间还晚,来指定回调函数:
在这里插入图片描述

3,promise的回调函数,都是异步执行的

在这里插入图片描述
看这段代码,resolve(1)是同步执行的,.then()也是同步执行的,这时候,状态已经改变,回调函数也指定好了,那么它是同步执行的吗?不,它是异步执行的,可以由------先输出从而判断出来。

4,promise.then()返回的新promise的结果状态是由什么决定的?

(1),简单表达:由then()指定的回掉函数的执行结果决定
(2),详细表达:

1,如果抛出异常,新promise变为rejected状态,reason为抛出的异常
2,如果返回的是非promise的任意值,新promise变为resolved,value为返回的值。
3,如果返回的是另一个新的promise,此promise的结果就会变成新promise的结果

new Promise((resolve,reject)=>{
	resolve(1)
}).then(
	value=>{
		console.log('onResolved1()',value)
		//return 2
		//return Promise.resolve(3)
		//return Promise.reject(4)
		throw 5
	},
	reason=>{
		console.log('onRejected1()',reason)
	}
).then(
	value=>{
		console.log('onResolved2()',value)
	},
	reason=>{
		console.log('onRejected2()',reason)
	}
)
//r啥也不return时,返回结果是:onResolved1() 1  onResolved2() underfined ,因为没有指定value的值
//return 2时,即为返回非promise的任意值,新promise变为resolved,value为返回的值2。于是结果onResolved1() 1  onResolved2() 2 
//return Promise.resolve(3)时,返回的是另一个新的promise,此promise的结果就会变成新promise的结果3
//于是返回的结果是:onResolved1() 1  onResolved2() 3
//return Promise.reject(4)和上一个一样,返回的最终结果:onResolved1() 1  onRejected2() 4
//throw 5,如果抛出异常,新promise变为rejected状态,reason为抛出的异常
//最终的结果:onResolved1() 1  onRejected2() 5

由此可以知道,链式写promise中,第一个异步操作的promise失败 了并不会导致后续的promise失败,后续的promise的失败与否还是由新promise决定的。

5,promise的异常传透

1,当使用promises的then链式调用时,可以在最后指定失败的回调。
2,前面的任何操作出了异常,都会传递到最后的失败中处理

6,中断promise链

1,当使用promise的then链式调用时,在中间中断,不再调用后面的回调函数。
2,办法:在回调函数中返回一个pendding状态的promise对象

在这里插入图片描述
原理就是返回的新promise没有结果,所以就不会继续调用reject或者resolve,所以就中断了这个链……

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值