建议收藏!async ,await相关知识总结,适用于js基础不错的童鞋

早在很久之前就知道async和awiat的大名了,但我却一直对这个东西也算是不温不火吧;
最近在搞koa的时候 大量出现的 async和await把我搞得有点烦了;
我就单独抽出来 半天时间 好好来解决下整个async和await
可能有的童鞋知道 他是基于es6的promise基础上进行扩展了;
在讲解之前我们就来谈谈 promise的由来的历史吧; 虽然有点废话了 但助你理解async的还是有点帮助的.
1.promise的历史
可能会碰见 这样的面试 会什么会有 promise这个东西,他的存在是为了解决什么的
很多童鞋 可能都会说出来 是来解决回调地狱的问题 那么问题来了 能详细谈一谈什么是回调地狱呢;
当然这个问题 对于一些很厉害的 童鞋也不算什么问题,
这里我要说一个他的另一个由来的原因
在很久很久之前的
我们在一个函数内部 如果有异步函数的话 怎么获取到 异步函数里面的变量呢
可能手快的童鞋 就直接在异步函数中进行了 return 但是真的能拿到吗?
 

function test(){
	setTimeout(()=>{
		return "hello world"
	},1000)
}
console.log(text())  // undefined 

上面的原因是由于 函数内部 立即执行完毕 并不会等待 异步函数的执行完毕 在同步那块什么都没有返回东西 打印当然是 undefined
那我们怎么拿到 异步里面执行的变量呢
// 以前的程序员的解决方法就是 使用回调函数 

function test(callback){
	setTimeout(()=>{
		callback("hello world")
	},1000)
}
test(function(msg){console.log(msg);});

上面的程序其实可以看成下面的这种情况 

function test(callback){
	setTimeout(()=>{
		callback("hello world")
	},1000)
}
var callback=function(msg){
	console.log(msg)
}
test(callback)

但问题是 如果工作中也想这么简单就好了 前端的同行都知道 经常要和服务器进行ajax交流
但是交流就交流吧 还经常 下一个ajax交流的参数依赖上一个ajax交流的结果
这就形成了 嵌套 问题是有的时候套一层还不够 还得套好几层 这就产生了回调地狱的问题了
这个时候promise就诞生了
我们这里使用promise将上面的程序进行修改下
 

function test(){
	return new Promise((resolve,reject)=>{
		setTimeout(()=>{
			resolve("hello world");
		},1000)
	})
	
}
test().then(res=>{console.log(res)}) // 输出 hello world

是不是看起来就有那么一丝感觉了是吧
函数体内部返回一个new promise函数
在函数执行后 有一个.then方法 来接收 执行成功的 内部 
我们可以把变量放到 resolve() 里面作为参数 在 .then中用来接收
但是 promise 我就不在这里细讲了 可以去看看阮一峰老师的 es6
2.async 和await
在学习async和await 之前 不要把它当做一个新知识来说
他不过是我们之前学过的东西 穿上了 一层新的衣服 首先内心上就不够对他产生恐惧
官方解释一大堆专业名词 ,那就不要去看了 ,越看越迷惑
通俗的讲解就是 就是将 你的异步代码 看起来更像是 同步 不要将它想的太高大上

我依次举几个例子 你们可能就懂了
1.函数前面加上 async 之后 函数返回一个 promise对象
 

async function test(){
	console.log(111);
}
console.log(test());

 建议收藏!async ,await相关知识总结,适用于js基础不错的童鞋

 如果函数里面没有 返回数据的话 就是 在promise 后面就是一个undefined
2.带返回值的函数

async function test(){
	return "111";
}
console.log(test());

建议收藏!async ,await相关知识总结,适用于js基础不错的童鞋

 那我们怎么拿到那个返回值呢
聪明的童鞋可能就想到了 既然是promise对象 那就按照promise的那种方式拿呗
bingo clever!

async function test(){
	return "111";
}
test().then(res=>{console.log(res)}); // 输出 111

 3.在没有 await 关键字之前 不要把sync 当做异步看待 他里面的执行体 只要不是异步代码 和同步带吗一视同仁
按照正常顺序走就是了

async function test(){
	console.log(111);
}
test();
console.log(2222);

建议收藏!async ,await相关知识总结,适用于js基础不错的童鞋 

4.await 关键字
记住了await必须只能在  前面有async 的函数体内 否则报错
这里先举一个正常点的例子吧
这里可以先暂停下 知道点await的童鞋可以先去标注下下面的输出顺序

function func(){
	return new Promise((resolve)=>{
		setTimeout(()=>{
			console.log(111);
			resolve('222');
		},3000)
	})
}
async function test(){
	var n=await func();
	console.log(n);
	 console.log(333);
}
test();
console.log(444);
// 答案 : 1.444  2.111  3.222   4.333 

这个await 要关键进行讲解了
await 后面 要等待的函数 对象有两种1,返回promise 2.不返回promise的
这两者之前下面又分为 返回的是同步还是异步 有没有返回值 下面都进行讲解
有一个很重要的一点就是 不管上面得是那种情况 await 都会阻塞它下面代码的执行

4.1 先说下 不返回promise的函数对象吧 且是同步的代码 没有返回值
// await 会阻塞 下面的代码执行 先执行函数外面的 同步 代码
所以下面的输出顺序是 111 333 222
 

function func(){
	console.log(111);
}
async function test(){
	await func();
	console.log(222);
}
test();
console.log(333);

 建议收藏!async ,await相关知识总结,适用于js基础不错的童鞋

4.2 await 不返回promise对象的函数对象吧 且是同步的代码 有返回值的
await 是代码从右向左执行的 左边的函数执行完之后 有返回值复制给 n
下面代码的执行顺序是 333 111 222 

function func(){
	return "111";
}
async function test(){
	var n=await func();
	console.log(n);
	console.log(222);
}
test();
console.log(333);

4.3 await 不返回promise对象的函数对象吧 且是异步的代码 没有返回值的
还是要记住 await 会阻塞后面代码的执行 先执行 外边的同步代码
下面函数的执行顺序是 111 444 333 222

function func(){
	console.log(111);
	setTimeout(()=>{
		console.log(222);
	},1000)
}
async function test(){
	await func();
	console.log(333);
}
test();
console.log(444);

这里可能有的童鞋纳闷了 不是阻塞后面代码的执行 先执行 完await 后面的函数么
这里确实 执行完了 看见那个 111 是先打印的
但是 后面有一个异步函数 它自然要进入 异步的事件队列里面 等待 定时 事件走完 他就要执行了
所以 这下 自然 人家后面的 333 就要执行了
awati 是让代码看起来像是同步 的 并不是 代码走的也变成同步阻塞了哈

4.4 await 不返回promise对象的函数对象吧 且是异步的代码 有返回值的(迷惑人呢)
下面的输出 自然就是 // 111 444 undefined 333
func 执行完了 没有返回值 自然是对的 就是undefined了
那个说人家异步函数里面有返回值的 那个func函数都执行完了 这个值 是拿不到外边
要想拿到 就看下面的promise吧
 

function func(){
	console.log(111);
	setTimeout(()=>{
		return "222";
	},1000)
}
async function test(){
	var n=await func();
	console.log(n);
	console.log(333);
}
test();
console.log(444);

4.5 await 返回promise对象的函数对象吧 且不是异步的代码 没有返回值的
这里输出的顺序就是 111 333
这里可能纳闷 为啥子 没有 222
要记牢 如果 返回的是promise对象的话 没有返回值
await 等不到 返回值的话 下面的代码他就不执行了 记住这点 哦 童鞋们

function func(){
	return new Promise((resolve,reject)=>{
		console.log(111);
	})
}
async function test(){
	await func();
	console.log(222);
}
test();
console.log(333);

 4.6 await 返回promise对象的函数对象吧 且是异步的代码 没有返回值的
// 下面代码的输出 顺序 是 333 111
同样没有收到返回值 直接不执行下面的 console.log(222)了

function func(){
	return new Promise((resolve,reject)=>{
		setTimeout(()=>{
			console.log(111);
		},100)
	})
}
async function test(){
	await func();
	console.log(222);
}
test();
console.log(333);

 4.7 await 返回promise对象的函数对象吧 且不是异步的代码 有返回值的
// 下面的执行顺序是 111 444 222 333

function func(){
	return new Promise((resolve,reject)=>{
		console.log(111);
		resolve(222);
	})
}
async function test(){
	var n=await func();
	console.log(n);
	console.log(333);
}
test();
console.log(444);

4.8 await 返回promise对象的函数对象吧 且是异步的代码 有返回值的
下面代码的执行顺序是 111 444 222 333
await 知道返回的是promise 它要拿到 返回的值 赋值给 n 所以就是打印出来这个顺序了

function func(){
	return new Promise((resolve,reject)=>{
		console.log(111);
		setTimeout(()=>{
			resolve(222);
		},1000)
	})
}
async function test(){
	var n=await func();
	console.log(n);
	console.log(333);
}
test();
console.log(444);

这下 应该就明白
最后 附上一到async 和await的经典面试题

async function async1(){
    console.log('async1 start') 
    await async2()
    console.log('async1 end')  
}
async function async2(){
    console.log('async2')  
}
console.log('script start'); 
setTimeout(function(){
    console.log('setTimeout')
},0)  
async1();
new Promise(function(resolve){
    console.log('promise1') 
    resolve();
}).then(function(){
    console.log('promise2') 
})
console.log('script end')

 

上一篇:011Java并发包009辅助类


下一篇:net core 中间件 MiddleWare 三种方式