Shyno
Don't be shy,no problem!

 

异步问题

在解释async 函数前,我们先可以看看普通的函数为什么处理不了异步问题

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请求线程)是一样的.

所以,无论如何,常规的写法都没法避免这个问题.那我们看看以往的异步问题是怎么处理的?

 

 

首先是回调函数,也就是说根据不同的状态执行不同的回调函数.但是假如嵌套多层就对代码的观感和维护很不友好.但是,"回调函数"是正解,,不过其有个违和点.就是你先得知道他是异步的,你的同步代码得迁移到回调函数里面,得改成.

function Myobject (){
       setTimeout(()=>{
          console.log('1')
          if(条件满足){
          console.log('2')
}
       },100)
   } 

Promise,它不进行所谓的嵌套,而是进行链式调用,解决了"回调地狱"问题.但它其实也是一种回调函数,只不过换种方式调用,所以它也一样,你得先意识到他是异步,然后去修改你的代码

这两种方案的特点其实都是,用特殊的方式把函数进行顺序的调用.而且都是完整的函数,这点很重要.同时他不太符合我们的写代码习惯.

 

Generator 函数

然后我们回到Generator 函数身上,看以下例子

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 函数有的特点它都有,如下

 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函数,特点是更加符合一般函数的代码书写习惯,它不做函数的管理,而是代码块的管理

 

 

 

posted on 2022-08-08 16:53  Shyno  阅读(50)  评论(0编辑  收藏  举报