异步问题
在解释async 函数前,我们先可以看看普通的函数为什么处理不了异步问题
1 2 3 4 5 6 | function Myobject (){ setTimeout(()=>{ console.log( '1' ) },100) console.log( '2' ) } |
这里需要明确几点:
1.js代码是从上往下执行的.且不出错的情况下会一直执行下去
2.异步产生的原因是浏览器是多线程的.(js线程是单线程)
3.异步问题多是指回调函数.
然后我们在解析一下当这个函数被执行是会怎么样?首先,setTimeout会被执行,也就是说会由定时触发器线程开始计时,但是不会打印,你可以理解为(console.log('1')实际上是计时结束后的回调函数,它由事件触发线程保存,然后由js线程打印'2'.最后事件触发线程把对应的事件交给再交给js线程去执行,最后才打印"1".
这里我们把定时器(定时触发器线程)换成http请求(http请求线程)是一样的.
所以,无论如何,常规的写法都没法避免这个问题.那我们看看以往的异步问题是怎么处理的?
首先是回调函数,也就是说根据不同的状态执行不同的回调函数.但是假如嵌套多层就对代码的观感和维护很不友好.但是,"回调函数"是正解,,不过其有个违和点.就是你先得知道他是异步的,你的同步代码得迁移到回调函数里面,得改成.
1 2 3 4 5 6 7 8 | function Myobject (){ setTimeout(()=>{ console.log( '1' ) if (条件满足){ console.log( '2' ) } },100) } |
Promise,它不进行所谓的嵌套,而是进行链式调用,解决了"回调地狱"问题.但它其实也是一种回调函数,只不过换种方式调用,所以它也一样,你得先意识到他是异步,然后去修改你的代码
这两种方案的特点其实都是,用特殊的方式把函数进行顺序的调用.而且都是完整的函数,这点很重要.同时他不太符合我们的写代码习惯.
Generator 函数
然后我们回到Generator 函数身上,看以下例子
1 2 3 4 5 6 7 8 9 10 | function * helloWorldGenerator() { yield console.log( '444' ); yield console.log( '555' ); console.log( '33' ) } var hw = helloWorldGenerator() hw.next() hw.next() hw.next() |
它有以下几个特点
1.它看起来就像个多了点奇怪东西的普通函数(目的),
2.它被调用的时候并不会直接执行里面的所有代码.
3.它里面的代码会被分成好几部分,每个部分按顺序且单独执行且可以有返回值.所以我们完全可以根据上一步的执行结果来判断是不是执行下一步.
具体的原理可以单独去查一下
async函数为什么能处理异步函数
首先,async函数是Generator 函数的语法糖,也就是说Generator 函数有的特点它都有,如下
1 2 3 4 5 6 7 8 9 | let helloWorldGenerator=async function () { await new Promise((resolve) => { setTimeout(resolve, 1000); }) await console.log( '555' ); console.log( '33' ) } var hw = helloWorldGenerator() |
那么它都做了哪些优化呢?
1.保留了看起来像普通函数的特点
2.把*和yield换成了async和await,语义化,更清晰
3.它不需要我们手动的去调用.next方法了,也就是说它自动帮我们加了判断,以及满足条件去调用下一个.next方法
其结果就是,我们可以像写一般函数那样去写带有异步任务的函数了.
总结,async函数实际上就是利用Generator函数的特性来处理异步问题的.它比起Promise函数,特点是更加符合一般函数的代码书写习惯,它不做函数的管理,而是代码块的管理
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架