async/await|青训营笔记

48 阅读3分钟

这是我参与「第五届青训营 」伴读笔记创作活动的第6天。

Generator函数

Generator 函数是 ES6 提供的一种异步编程解决方案,可以先理解为一个状态机,封装了多个内部状态,执行Generator函数返回一个遍历器对象,通过遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。

语法上,Generator 函数是一个普通函数,但是有两个特征。

function关键字与函数名之间有一个*;

函数内部使用yield表达式,定义不同的内部状态。

function* myGenerator() {
 	yield 'Hello'
    yield 'world'
    return 'ending'
}
let MG = myGenerator()
console.log(MG.next());
console.log(MG.next());
console.log(MG.next());
console.log(MG.next());

运行结果:

image.png 1)yield 表达式,可以在生成器函数内部暂停代码的执行,使其挂起,此时生成器函数仍然是运行并且是活跃的,其内部资源都会保留下来,只不过是处在暂停状态。

2)next(),在迭代器上调用next()方法,可以使代码从暂停的位置开始继续往下执行。

async/await
 const fs = require('fs')
 const readFile = function(fileName){
      return new Promise(function(resolve,reject){
            fs.readFile(fileName,function(error,data){
            if(error) return reject(error)
                resolve(data)
            })
     })
 }
//generator函数实现
 const gen=function* (){
      const f1 = yield readFile('/etc/fstab');
      const f2 = yield readFile('/etc/shells');
      console.log(f1.toString());
      console.log(f2.toString());
  }
//async实现
const gen1 = async function(){
   const f1 = await readFile('/etc/fstab');
   const f2 = await readFile('/etc/shells');
   console.log(f1.toString());
   console.log(f2.toString()) ;
}

由此可见,async和generator在语法上是类似的。

async做一件什么事情?

带async关键字的函数,它使得你的函数的返回值必定是promise对象

1)如果async关键字函数返回的不是promise,会自动用Promise.resolve()包装

2)如果async关键字函数显式地返回promise,那就以你返回的promise为准

async function fun1(){
  return 'hello'
}
function fun2(){
    return 'async'
}
console.log(fun1());
console.log(fun2());

image.png

await在等什么?

await等的是右侧「表达式」的结果右侧是指await下边的语句(代码)

async function async1(){
   console.log('async1 start');
    await async2()
    console.log('async1 end');
}
async function async2(){
    console.log('async2');
}
console.log('script start');
async1()

image.png

await等到之后,做了一件什么事情?

右侧表达式的结果,就是await要等的东西。

等到之后,对于await来说,分为2种情况

1)不是promise对象

2)是promise对象

如果不是 promise , await会阻塞后面的代码,先执行async外面的同步代码,同步代码执行完,再回到async内部,把这个非promise的东西,作为 await表达式的结果

如果它等到的是一个 promise 对象,await 也会暂停async后面的代码,先执行async外面的同步代码,等着 Promise 对象 fulfilled,然后把 resolve 的参数作为 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");

image.png

async和promise的区别

1)Async/Await 代码看起来简洁一些,使得异步代码看起来像同步代码

2)async await与Promise一样,是非阻塞的。

3)async await是基于Promise实现的,可以说是改良版的Promise,它不能用于普通的回调函数。

调试: promise

promise不能在返回表达式的箭头函数中设置断点 如果你在.then代码块中设置断点,使用Step Over快捷键,调试器不会跳到下一个.then,因为它只会跳过异步代码 async

async/await能够使得代码调试更简单 使用await/async时,你不再需要那么多箭头函数,这样你就可以像调试同步代码一样跳过await语句 如果它等到的不是一个 Promise 对象,那 await 表达式的运算结果就是它等到的东西。 如果它等到的是一个 Promise 对象,await 就忙起来了,它会阻塞后面的代码,等着 Promise 对象 resolve,然后得到 resolve 的值,作为 await 表达式的运算结果。 promise异步:

ajax('aaa',()=>{
   ajax('bbb',()=>{
        ajax('ccc',()=>{

        })
    })
})
ajax('aaa').then(res=>{
    return ajax('bbb')
}).then(res=>{
    return ajax('ccc')
})

async异步:

 async function fetch(){
     await ajax('aaa')
      await ajax('bbb')
      await ajax('ccc')
  }