由回调函数、Promise到async/await的同步写法执行异步代码

   日期:2020-05-01     浏览:121    评论:0    
核心提示:前端开发中同步和异步的区别以及转换同步异步是前端面试中经常遇到的问题,虽然不难,但是搞清楚两者之间的前端

由回调函数、Promise到async/await的同步写法执行异步代码

同步异步是前端面试中经常遇到的问题,虽然不难,但是搞清楚两者之间的关系和转换还是很重要

同步

同步是一种线性执行的方式,执行的流程不能跨越,其后的线程要阻塞等待前面线程的运行;同步可以保证顺序一致,但是容易导致阻塞,即同步是阻塞模式。

同步一般用于流程性比较强的程序,比如用户登录功能就是同步处理的,需要用户通过用户名和密码验证后才能进入系统。

最基础的JavaScript就是同步的,单线程,自上而下运行。

通俗的话说:同步就相当于是 当客户端发送请求给服务端,在等待服务端响应的请求时,客户端不做其他的事情。当服务端做完了才返回到客户端。这样的话客户端需要一直等待,导致用户体验比较差。

异步

异步是一种并行处理的方式,不必等待一个程序执行完,就可以执行其它的任务,即异步是非阻塞模式。在程序中异步处理的结果通常使用回调函数来处理结果。

异步可以解决阻塞问题,但是会改变顺序性。

通俗的话说:异步就是,当客户端发送给服务端请求时,在等待服务端响应的时候,客户端可以做其他的事情,这样节约了时间,提高了效率。

为什么会有异步

简单来说,没有异步只有同步的话,代码只能自上而下执行,若前面的代码解析时间很长,那么下面的代码就会被阻塞;而对于用户而言,阻塞就意味着"卡死",这样就导致了很差的用户体验,这时我们就需要异步来优化代码。

ES6新特性:Promise

promise 用同步的写法执行异步代码

Promise 优化了回调函数的用法,让原本需要纵向一层一层嵌套的回调函数实现了横向的调用,也就是链式调用

首先我们模拟一个异步时间,要求1s后输出hello world

function fn(){
    setTimeout(()=>{
        var call = "hello world";
   }, 1000);
}

问题来了,我们该如何输出hello world呢?

是这样吗?

function fn(){
     setTimeout(()=>{
         var call = "hello world";
    }, 1000);
	return call;
}
console.log(fn()); //Uncaught ReferenceError: call is not defined

不不不,这样会报错。这是因为setTimeout是异步执行,1s后才会执行 var call = “hello world”;这时会先执行return call;所以call is not defined

还是这样?

function fn(){
     setTimeout(()=>{
         var call = "hello world";
		 return call;
    }, 1000);
}
console.log(fn()); //undefined

不不不,这样也达不到预期效果!这是因为执行 console.log(fn()) 时,fn()没有返回值,所以undefined;而1s后再执行setTimeout

ES5:通过回调函数来处理异步执行的结果
function fn(callback){
     setTimeout(()=>{
         var call = "hello world";
		 callback(call);
    }, 1000);
}
fn(function(call){
	console.log(call); //hello world
});

通过回调函数,我们得到了想要的结果;但是在整体结构上,我们多了一个回调函数,这样看起来不太友好。于是,ES6的Promise诞生了!

ES6:通过Promise来处理异步执行的结果
function fn(resolve,reject){
     setTimeout(()=>{
         var call = "hello world";
		 resolve(call);
    }, 1000);
}
let p = new Promise(fn);
p.then(function(res){
	console.log(res); //hello world
})

Promise是同步的,它里面执行到异步任务以前都是同步执行的。当执行的异步任务的时候,就被挂起了,然后继续执行主线程Promise后面的代码。当异步任务有结果返回的时候,Promise的状态就改变啦!

Promise 构造函数接受一个函数作为参数,函数里面有两个参数 resolve 和 reject ,其中 resolve 作为执行成功的函数, reject 作为执行失败的函数

下面我们以一个小例子来讲解一下resolve和reject

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<button type="button">按钮</button>
		<script type="text/javascript">
			let oBtn = document.querySelector('button');
			//定义一个开关,通过按钮来控制开关的值是true还是false
			let Off = true; 
			oBtn.onclick = function(){
				function fn(resolve,reject){
				     setTimeout(()=>{
				         var call = "hello world";
						 if(Off){
							 Off = !(Off);
							 resolve(call);
						 }else{
							 Off = !(Off);
							 reject('获取失败!');
						 }
				    }, 1000);
				}
				let p = new Promise(fn);
				p.then((res) => {
					console.log(res);//hello world
				},(res) => {
					console.log(res);//获取失败!
				})
			}
		</script>
	</body>
</html>

多次点击按钮,上述代码会依次输出如图所示结果:

ES7新特性:async…await

1. async 将普通方法转为 异步并且返回 promise对象
2. await 将异步代码转为同步结果,等着异步代码执行完才执行后面的代码

怎么拿到异步数据?

方法一:

async 将普通方法转为 异步并且返回 promise对象

//async 将普通方法转为 异步并且返回 promise对象
async function test(){
	return 'goods';
}
console.log(test());//Promise {<resolved>: "goods"}
let p = test();
p.then(function(res){
	console.log(res); //goods
})
方法二:

await 必须在异步函数中使用

async function test(){
	return 'goods';
}
//await 必须在异步函数中使用
async function fn(){
	let data = await test(); 
	console.log(data); //goods
}
fn();

await 将异步代码转为同步结果,等着异步代码执行完才执行后面的代码

请仔细对比下面两个例子的输出!

async function fn1(){  
	return  '成功';
}
async function fn2(){
	console.log(1111);
	let  p = fn1();
	p.then(function(res){
		console.log(res);
	});
	console.log(3333);
}
fn2();

async function fn1(){  
	return  '成功';
}
async function fn2(){
	console.log(1111);
	// await 将异步代码转为同步结果,等着异步代码执行完才执行后面的代码
	let data = await fn1();  
	console.log(data);
	console.log(3333);
}
fn2();

同步异步的简单讲解就到这里了,若你有其它看法,欢迎指正,期待您的留言!

求学的三个条件是:多观察、多吃苦、多研究。——加菲劳

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服