目录
关于async_await ,首先让我给你们讲讲同步和异步的故事
1. 同步异步
1.1 故事片段1
function fn1 (){
setTimeout(()=>{
console.log(2);
},3000)
console.log(1);
console.log(3);
}
fn1()
执行结果:1、3、2
毫无疑问,简单,但是思考下我接下来的问题:如何让fn1 返回一个值5?
同步的做法
有的同学会说,我在代码最下面写一个`return 5` 不就可以了吗 ?
function fn1 (){
setTimeout(()=>{
console.log(2);
},3000)
console.log(1);
console.log(3);
return 5
}
console.log(fn1())
看下执行结果:1、3、5、2
如果,我们要让结果按小到大来输出,显然上面的代码不符合我的们要求,那么我们只能够在异步中来输出5
异步的做法
正确做法
通过提供一个回调函数,通过调用回调函数来返回值
function fn1 (callback){
setTimeout(()=>{
console.log(2);
callback(5)
},3000)
console.log(1);
console.log(3);
}
fn1((arg1)=>{console.log(arg1)})
错误做法
在定时器里用return 5
分析:首先将定时器放到异步队列,然后执行完输出1和3以后,函数就被跳出了,return将没有意义了。
【总结】故事片段一,教会你在一个包括同步和异步的函数里面返回一个值
1.2 故事片段二
欢迎大家进入故事片段二,我在这里提出一个小小的问题,大家动脑子解决一下。
如果我定义了一些函数如下,将fn1的返回值传入fn2,将fn2的返回值传入fn3
function fn1(n){
return n+1
}
function fn2(n){
return n+1
}
function fn3(n){
return n+1
}
问题很简单那,上解决代码
let result = fn1(10)
result = fn2(result)
result = fn3(result)
console.log(result)
但是,事情没有那么简单!!!
大家都发现了,上面的函数返回值都是在同步代码中定义的,那么异步代码中定义的该如何去解决这个问题呢?请回顾我们所说的提供回调函数的方法。
function fn1(n,callback){
setTimeout(()=>{
callback(n+1)
},1000)
}
function fn2(n){
return n+1
}
function fn3(n){
return n+1
}
解决方法
fn1((result)=>{
let result1 = fn2(result)
result1 = fn3(result)
console.log(result1)
})
1.3 故事片段3-回调地狱,金字塔
大家可能没发现,当我们将fn2和fn3 变为跟fn1一样的代码,我们再继续解决上面的问题时,代码将产生回调地狱,也就是在代码里一直使用回调函数的现象,不利于我们的理解,请看代码
fn1(10,(n)=>{
fn2(n,(n)=>{
fn3(n,(n)=>{
console.log(n)
})
})
})
2. 救世主 Promise
2.1 为什么把Promise当成救世主呢?
回调地狱的出现,必然让大家都感到麻烦,随着时间的发展,js提供了一个解决方案,那就是通过Promise来解决,因此Promise是我们的救世主。
函数 适合一些同步代码,异步代码不适合在函数里面写,如果要写的话也可以,经常会带来一些回调地狱问题
因此,对promise的定义是,在js中专门用来存储异步代码的对象
它能够确保异步代码的执行 ,并且可以确保返回异步代码的结果
then方法只有当代码正常执行的时候才会调用,代码出错用catch方法
然后 在then 方法return值会成为新的promise对象的值,可以继续调用then方法进行处理
//因此这么处理上面的需求
function f1(n){
return new Promise((resolve,reject)=>{
setTimeout(()=>{resolve(n+1)},1000)
})
};
function f2(n,callback){
setTimeout(()=>{
callback(n+1)
},3000)
}
function f3(n,callback){
setTimeout(()=>{
callback(n+1)
},3000)
}
````````````````````````````````
f1(10).then((n)=>f2(n))
.then((n)={f3(n)})
显然,代码只有这么两行
f1(10).then((n)=>f2(n))
.then((n)={f3(n)})
大大提高了我们的效率!!!!
恭喜你,了解了同步和异步,回调地狱,和Promise,接下来,让我们进入async和await的世界
3. async和await的世界
3.1 为什么存在async和await?
因为,每次在函数里面写异步代码都是return 一个promise 对象,这样总是很繁琐,所以async和await 就诞生了。
async 声明的函数,函数返回值会自动包装成promise对象
在async声明的函数里,可以用await 调用其他异步函数
可以在异步函数前用await关键字进行调用,使用await时,它会等待promise执行出结果后,将结果返回,返回的不是promise而是promise执行完的值。
注意:await 并不能够将异步代码变成同步代码
-
await 的使用位置: 写在async的内部、 可以在模块的外层作用域使用
-
当我们使用了await ,catch错误的方法就不能使用了,可以通过try{}catch(e){}来使用
3.2 强大的世界停止工具 await
await具有时间暂停的能力和yield关键字一样
await +promise 只有当promise 被正常resolve时才会被放进异步任务里面,如果抛出异常的话,后面的代码将会被忽略
await 修饰的异步任务会被放到异步队列里,同时让出js线程,当执行完所有同步代码时,才会按照顺序执行所有异步代码
请大家分别执行以下的代码,根据上面橙色的重点,看看处理结果,想一想执行顺序
3.3 Code
3.3.1 时间暂停
async function test1(){
console.log(2)
console.log(await Promise.resolve(5))
console,log(6)
}
async function test2(){
console.log(4)
console.log(await 7)
console,log(8)
}
console.log(1);
test1();
console.log(3);
test2();
3.3.2 await+Promise
async function test1(){
console.log(2)
console.log(await new Promise(()=>{
console.log('第一次进来');
setTimeout(() => {
console.log('第二次进来');
console.log(5)
}, 1000);
resolve()
}))
console,log(6)
}
async function test2(){
console.log(4)
console.log(await 7)
console,log(8)
}
console.log(1);
test1();
console.log(3);
test2();
3.3.3 await+Promise(特例)
async function test1(){
console.log(2)
console.log(await Promise.resolve(5))
console,log(6)
}
async function test2(){
console.log(4)
console.log(await 7)
console,log(8)
}
console.log(1);
test1();
console.log(3);
test2();
3.3.4 最后来一个简单的应用-睡觉
// sleep函数
function sleep(time){
return new Promise((resolve)=>{
setTimeout(() => {
resolve()
}, time);
})
}
async function test(){
await sleep(5000)
console.log('5秒后执行');
}
【后记】码字不易
首先,谢谢大家看完我的文字,文字不多,但是可以让你了解到变化,让你 对js有进一步的了解。
其次,请大家不要放弃前端的学习,卷起来吧。
然后喜欢我的,点个关注,谢谢