Promise与async/await的理解

目录

前言

了解同步和异步

了解异步

1.宏任务与微任务

2.宏任务与微任务的执行顺序

了解Promise

1.Promise(承诺)

2.Prpmise的方法

了解async/await

1.async/await     

试题

1.使用Promise与async/await分别输出1,2

 2.再了解异步与同步的输出顺序

3.最后我们用setTimeout模拟异步操作,用Promise和Async/Await分别来实现下

总结


前言

        最近翻了许多资料去了解Promise,async/await。可以从一个出发点去理解,我们JavaScript是一门单线程语言(single thread,指一次只能完成一件任务,如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务,以此类推),而异步在浏览器中大致分为(定时器模块、Ajax模块、DOM模块)

了解同步和异步

  • 基于 JS 是单线程编程语言
  • 同步会阻塞代码执行
  • 异步不会阻塞代码执行: ==> ajax请求, send()发异步/同步请求的对比

了解异步

1.宏任务与微任务

         首先,什么是宏任务,微任务?

         js 是一种单线程语言,简单的说就是:只有一条通道,那么在任务多的情况下,就会出现拥挤的情况,这种情况下就产生了 ‘多线程’ ,但是这种“多线程”是通过单线程模仿的,也就是假的。那么就产生了同步任务和异步任务。

        异步任务分为宏任务,微任务。

宏任务微任务
scriptProcess.nextTick(node.js)
setTimeoutPromise
setIntervalMutationObserver
setImmediate(浏览器暂时不支持,只有IE10支持)async/await
I/OObject.observe
UI Rendering
requestAnimationFrame(存在争议)

2.宏任务与微任务的执行顺序

         先执行同步再执行异步,异步遇到微任务,先执行微任务,执行完后如果没有微任务,就执行下一个宏任务,如果有微任务,就按顺序一个一个执行微任务

了解Promise

1.Promise(承诺)

        Promise,翻译过来是承诺,承诺它过一段时间会给你一个结果。从编程讲Promise 是异步编程的一种解决方案。下面是Promise在MDN的相关说明:

        Promise 对象是一个代理对象(代理一个值),被代理的值在Promise对象创建时可能是未知的。它允许你为异步操作的成功和失败分别绑定相应的处理方法(handlers)。 这让异步方法可以像同步方法那样返回值,但并不是立即返回最终执行结果,而是一个能代表未来出现的结果的promise对象。

一个 Promise有以下几种状态:

  • pending: 初始状态,既不是成功,也不是失败状态。
  • resolve/fulfilled: 意味着操作成功完成。
  • rejected: 意味着操作失败。

这个承诺一旦从等待状态变成为其他状态就永远不能更改状态了,也就是说一旦状态变为 fulfilled/rejected 后,就不能再次改变。 

2.Prpmise的方法

        Promise的方法有很多如resolve(),reject()then(),catch(),all(),race()等等,这里我就不细谈了

了解async/await

1.async/await     

async/await是一种建立在Promise之上的编写异步或非阻塞代码的新方法,被普遍认为是 JS异步操作的最终且最优雅的解决方案。相对于 Promise 和回调,它的可读性和简洁度都更高。毕竟一直then()也很烦。

async 是异步的意思,而 await async wait的简写,即异步等待。

所以从语义上就很好理解 async 用于声明一个 function 是异步的,而await 用于等待一个异步方法执行完成。

一个函数如果加上 async ,那么该函数就会返回一个 Promise

试题

1.使用Promise与async/await分别输出1,2

Promise用法

//使用Promise输出1,2
function foo(){
    //利用Promise的resolve成功在调用then(resolve))返回的是成功的
	Promise.resolve().then((resolve)=>{
		console.log(1);
	})
	console.log(2);
}
foo()
//执行顺序为首先判断代码为同步还是异步
//判断Promise为异步,再判断为它为宏任务还是微任务,根据它是什么任务再放入它本身的队列当中
//首先执行同步代码,再进行异步代码

//结果为2,1

async/await再执行这段代码

async function foo(){
	await Promise.resolve().then((resolve)=>{//await为步数,带有顺序,从上往下
			console.log(1);
	})
	console.log(2);
}
foo()
//利用async/await调用函数
//输出的结果为1,2
//原因为async/await将异步转换成同步了


 2.再了解异步与同步的输出顺序

        console.log('start');
		Promise.resolve().then((resolve)=>{
			console.log(1);
		})
		async function fn(){
			console.log(2);
			await console.log(3);
			console.log(4);
		}
		fn()
		setTimeout(()=>{
			console.log("setTimeout1");
		},0)
		async function fn1(){
			await new Promise(resolve=>{
				setTimeout(()=>{
					console.log('setTimeout2');
					resolve()
				},0)
			})
		}
		fn1()
		async function fn2(){
			await Promise.resolve().then(resolve=>{
				console.log(5);
			})
		}
		fn2()
		console.log('end');

结果为:

是不是与你的猜想不一样^v^ 

那我们来分析一下吧!

        console.log('start');     //为同步
		Promise.resolve().then((resolve)=>{//为异步  为微任务放入微任务队列
			console.log(1);
		})
		async function fn(){//为同步
			console.log(2);//为同步
			await console.log(3);//为异步  并且为微任务下一个执行
			console.log(4); //本来为同步,但是因为await,改变为微任务放入微任务队列
		}
		fn()
		setTimeout(()=>{
			console.log("setTimeout1");  //为异步  为宏任务放入队列
		},0)
		async function fn1(){//为同步
			await new Promise(resolve=>{ //为同步
				setTimeout(()=>{ //为异步  为宏任务放入队列
					console.log('setTimeout2');
					resolve()
				},0)
			})
		}
		fn1()
		async function fn2(){
			await Promise.resolve().then(resolve=>{//为异步  为微任务放入微任务队列
				console.log(5);
			})
		}
		fn2()
		console.log('end');//为同步


        //所以输出为   start,2,3,end
        //1,4,5
        //setTimeout1
        //setTimeout2

现在是不是清晰了很多呢?

3.最后我们用setTimeout模拟异步操作,用Promise和Async/Await分别来实现下

Promise

        // 传入一个初始值
		function sync(n) {
			return new Promise(resolve => {
				setTimeout(() => resolve(n + 500), n)
				// 定时器在n秒后触发
			})
		}

		// 调用函数的也需要调用参数n
		function fn1(n) {
			console.log("start", n);
			return sync(n)
		}

		function fn2(n) {
			console.log("loading", n);
			return sync(n)
		}

		function fn3(n) {
			console.log("end", n);
			return sync(n)
		}
        
       function fn(){
		    let num=0
			fn1(num).then((num1)=>fn2(num1))
			.then((num2)=>fn3(num2))
			.then((res)=>{
				console.log("result is",res);
			})
		}
		fn()

async/await:

		// 传入一个初始值
		function sync(n) {
			return new Promise(resolve => {
				setTimeout(() => resolve(n + 500), n)
				// 定时器在n秒后触发
			})
		}

		// 调用函数的也需要调用参数n
		function fn1(n) {
			console.log("start", n);
			return sync(n)
		}

		function fn2(n) {
			console.log("loading", n);
			return sync(n)
		}

		function fn3(n) {
			console.log("end", n);
			return sync(n)
		}

		// 调用
		async function init(){
			let num=0;
			let f1=await fn1(num)
			let f2=await fn2(f1)
			let result=await fn3(f2)
			console.log("result",result);
		}
		init()

结果为:

其实Promise与async/await输出的结果是一样的,只是async/await会更好理解一些,所以我们认为async/await是Promise或者Generator的语法糖。更仔细的我也描述的不太好,大家可以参考文案:「硬核JS」深入了解异步解决方案 - 掘金 (juejin.cn)

总结

哈哈哈,其实我没有总结

水平有限,欢迎指错

码字不易,大家有收获别忘了点个赞鼓励下

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值