JS总结——Promise与async,await

本文介绍了Promise在JavaScript中的作用,如何解决回调地狱,以及如何通过链式调用来组织异步操作。重点讲解了Promise的状态转换、回调函数的使用和返回值的特性。通过实例演示了同步和异步情况下的Promise应用,同时提到了Promise的静态方法和异常穿透机制。
摘要由CSDN通过智能技术生成

Promise是什么?

Promise是JS中进行异步编程的新解决方案(ES6规范)
异步任务:例如文件IO,AJAX,定时器等等,异步任务,简单地说,异步任务就是把任务先放一放,等当前手头的任务处理完之后再处理。

为什么要使用Promise

在Promise出现之前,我们想要执行异步函数,必须先指定其回调。
如果想要在基于第一个异步任务的处理结果执行第二个异步任务,那么我们就需要再第一个异步任务的回调函数中编写第二个异步任务的回调函数。
这样会产生一个回调地狱的问题。
请添加图片描述
如图所示,代码疯狂缩进,回调函数疯狂嵌套,即不便于阅读,也不利于异常处理

于是就产生了Promise这种解决方案,Promise通过链式调用的解决方案,解决回调地狱问题,同时能有效的处理异常。

链式调用,简单地说就是promise.then().then().then()通过.连接像一条锁链一样一个一个接着调用。

如何使用Promise

Promise执行流程图
我们可以通过Promise执行流程图对Promise有一个简单的认识。
在这里插入图片描述
再看一下Promise的结构,关键的有

  • PromiseState是Promise状态
  • PromiseResult是Promise结果

Promise的使用分为三个流程:改变Promise状态,指定回调,执行回调

  • Promise的状态有哪些?pendding(初始化状态,表示未发生改变),resolved(成功的状态),reject(失败的状态),
  1. 如何改变Promise状态?调用resolve或reject,每个Promise的状态只能修改一次

  2. 如何指定回调?首先获取promise实例对象,调用实例对象身上的.then()函数,并传入两个函数,第一个是成功的回调(resolve调用时执行),第二个是失败的的回调(reject调用时执行)。 then可以只指定成功的回调,如果只指定失败的回调的话使用.catch(()=>{})其中传入失败的回调

  3. 如何执行回调?promise状态改变,即resolve或reject调用的时候自动执行

解决了上述三个问题,我们来看看具体的代码

Promise内执行函数同步

使用Promise首先我们需要创建一个Promise对象(new Promise()),此时我们Promise的状态是pendding,然后在其中传入一个执行函数,由于我们当前函数内执行内容没有异步任务,该函数的内容是同步执行的。

	let p = new Promise((resolve,reject)=>{//在这个位置Promise的状态是pendding
		//执行一些任务
		if(success)
		resolve()  //如果调用,则Promise状态修改为resolved
		else
		reject() 	//如果调用,则Promise状态修改为rejected
	})

由于一个Promise的状态只能修改一次,因此如果在Promise执行器函数中两个resolve和reject都调用,Promise的状态取决于先执行的修改状态函数

	let p = new Promise((resolve,reject)=>{
		resolve()  //Promise状态修改为resolved
		reject() 	//状态不修改
	})

指定回调用Promise实例对象身上的.then()

	p.then(
	(res)=>{//成功的回调当resolve执行时执行
		console.log("success")
	),
	(res)=>{//失败的回调,当reject执行时执行
		console.warn("fail")
	})

调用顺序如下

	let p = new Promise((resolve,reject)=>{ 1//状态为pendding
		//执行一些任务
		resolve()  2//执行resolve(),状态为resolved
		reject() 	
	})
	p.then(  3//执行回调函数
	(res)=>{
		console.log("success")  4//执行成功的回调
	),
	(res)=>{
		console.warn("fail")
	})

Promise内执行函数异步

Promise只执行同步任务显然没发挥出其真正威力,毕竟Promise就是专门解决异步编程问题的,当Promise 内执行函数为异步,执行顺序如下

	let p = new Promise((resolve,reject)=>{ 1//状态为pendding
		setTimeOut( //这里设置了定时器,将任务转化为异步
		()=>{
			//执行一些任务
			resolve()  3//Promise改变状态为resolved
			reject() 	
			},1000
		)
	})
	p.then(  2//指定回调函数,此时回调函数已被指定
	//即成功时执行第一个函数,失败时执行第二个函数,但是函数未执行,
	(res)=>{
		console.log("success")  4//执行成功的回调
	),
	(res)=>{
		console.warn("fail")
	})

关键总结:只有调用resolve或reject,才执行回调

.then()的返回值

.then()的返回值是Promise实现链式调用的关键,当我们的.then()内函数的返回值是除了Promise的任意值时,返回一个新的resolved状态的Promise对象,新Promise对象的结果就是.then()内函数的返回值

	let res = p.then(
	(res)=>{
		console.log("success")  
		//如果没有return,则返回值未undefined
		return "123"
		),
	(res)=>{
		console.warn("fail")
	})
	//此时res是一个resolved状态的Promise,其PromiseResult是123

如果抛出异常,则res的状态为失败,结果为异常内容

	let res = p.then(
	(res)=>{
		console.log("success")  
		throw "fail"
		),
	(res)=>{
		console.warn("fail")
	})
	//此时res时一个reject状态,fail内容的Promise对象

如果返回的是一个Promise对象,则.then()的返回值就是该Promise对象

	let res = p.then(
	(res)=>{
		console.log("success")  
		return new Promise((resolve,reject)=>{
				resolve("success")
			)
		),
	(res)=>{
		console.warn("fail")
	})
	//此时res时一个resovled状态,success内容的Promise对象

由于返回值均为Promise对象,因此我们就可以进行链式调用了。

几个Promise的静态方法

  • Promise.resolve(value) 如果value是一个非Promise对象,则函数返回值是一个Promise对象,结果为value
    如果value是一个Promise对象,则返回值就是该Promise对象

  • Promise.reject(reason) 返回一个失败的Promise对象,结果为reason

  • Promise.all(promises) 返回一个新的promise,promises是一个包含多个promise的数组,当所有promise状态都为resolved,返回的promise状态才为resolved,状态为rejected

  • Promise.race(promises) 返回一个新的promise,promises是一个包含多个promise的数组,只要有其中一个promise先改变状态,其状态就是返回的promise的状态,其结果就是返回的promise的结果。

Promise的异常穿透

当使用promise.then()的链式调用时,可以在最后指定失败的回调,前面出了任何异常,都会传到最后的失败回调中处理
(前提是之前的所有函数都未指定失败的回调)

let p = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('OK');
            }, 1000);
        });

        p.then(value => {
            // console.log(111);
            throw '失败啦!';
        }).then(value => {
            console.log(222);
        }).then(value => {
            console.log(333);
        }).catch(reason => {
            console.warn(reason);
//在第一个.then()中的异常,在最后处理,之前所有成功的回调都不会执行
        });

async与await

  • async就是Promise对象的语法糖,async function a 相当于Promise.resolve(function a)

  • await如果右侧为promise则返回promise
    通常我们都将async和await同时使用

  • await中如果抛出异常,我们可以在async中捕获异常并处理,如果抛出异常,则async在await抛出异常之后的代码将无法执行。

  • await只阻塞当前作用域,即函数执行到await那一行时,当前作用域下还未执行所有代码都等到await异步任务执行完毕之后再执行,而不会影响其他作用域函数的执行

 async function main(){
            let p = new Promise((resolve, reject) => {
                // resolve('OK');
                reject('Error');
            })
            //1. 右侧为promise的情况
            // let res = await p;
            //2. 右侧为其他类型的数据
            // let res2 = await 20;
            //3. 如果promise是失败的状态
            try{
                let res3 = await p;
            }catch(e){
                console.log(e);
            }
        }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黑白程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值