event loop async await 事件循环机制 ---学习笔记

22 篇文章 0 订阅
4 篇文章 0 订阅

首先由一个小题目导入~~~~ ???

console.log(1) // 同步任务进入主线程
setTimeout(fun(),0)   // 异步任务,被放入event table, 0秒之后被推入event queue里
console.log(3) // 同步任务进入主线程

为什么setTimeout的延迟时间是0毫秒却在最后执行的???

1、3是同步任务马上会被执行,执行完成之后主线程空闲去event queue(事件队列)里查看是否有任务在等待执行.

node.js 有所体现~~~???

node.js的事件循环(eventloop)是怎么运作的?

1、每个Node.js进程只有一个主线程在执行程序代码,形成一个执行栈(execution context stack)。

2、主线程之外,还维护了一个"事件队列"(Event queue)。当用户的网络请求或者其它的异步操作到来时,node都会把它放到Event Queue之中,此时并不会立即执行它,代码也不会被阻塞,继续往下走,直到主线程代码执行完毕。
3、主线程代码执行完毕完成后,然后通过Event Loop,也就是事件循环机制,开始到Event Queue的开头取出第一个事件,从线程池中分配一个线程去执行这个事件,接下来继续取出第二个事件,再从线程池中分配一个线程去执行,然后第三个,第四个。主线程不断的检查事件队列中是否有未执行的事件,直到事件队列中所有事件都执行完了,此后每当有新的事件加入到事件队列中,都会通知主线程按顺序取出交EventLoop处理。当有事件执行完毕后,会通知主线程,主线程执行回调,线程归还给线程池。
4、主线程不断重复上面的第三步。

     

异步函数这么多,处理起来是不是麻烦???这时候有 async await  解决这类问题??? 

什么是 async 函数

一句话,它就是 Generator 函数的语法糖。

院一峰老师es6文中,

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);
    });
  });
};

const gen = function* () {
  const f1 = yield readFile('/etc/fstab');
  const f2 = yield readFile('/etc/shells');
  console.log(f1.toString());
  console.log(f2.toString());
};

上面代码的函数gen可以写成async函数,就是下面这样。

const asyncReadFile = 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,将yield替换成await,仅此而已.

综合以上 来2个案例 理解下~~~???

 案例1 

new Promise(function (resolve) { 
    console.log('1')// 宏任务一
    resolve()
}).then(function () {
    console.log('3') // 宏任务一的微任务
})
setTimeout(function () { // 宏任务二
    console.log('4')
    setTimeout(function () { // 宏任务五
        console.log('7')
        new Promise(function (resolve) {
            console.log('8')
            resolve()
        }).then(function () {
            console.log('10')
            setTimeout(function () {  // 宏任务七
                console.log('12')
            })
        })
        console.log('9')
    })
})
setTimeout(function () { // 宏任务三
    console.log('5')
})
setTimeout(function () {  // 宏任务四
    console.log('6')
    setTimeout(function () { // 宏任务六
        console.log('11')
    })
})
console.log('2') // 宏任务一
  • 全部的代码作为第一个宏任务进入主线程执行。
  • 首先输出1,是同步代码。then回调作为微任务进入到宏任务一的微任务队列。
  • 下面最外层的三个setTimeout分别是宏任务二、宏任务三、宏任务四按序排入宏任务队列。
  • 输出2,现在宏任务一的同步代码都执行完成了接下来执行宏任务一的微任务输出3。 第一轮事件循环完成了
  • 现在执行宏任务二输出4,后面的setTimeout作为宏任务五排入宏任务队列。 第二轮事件循环完成了
  • 执行宏任务三输出5,执行宏任务四输出6,宏任务四里面的setTimeout作为宏任务六。
  • 执行宏任务五输出7,8。then回调作为宏任务五的微任务排入宏任务五的微任务队列。
  • 输出同步代码9,宏任务五的同步代码执行完了,现在执行宏任务五的微任务。
  • 输出10,后面的setTimeout作为宏任务七排入宏任务的队列。 宏任务五执行完成了,当前已经是第五轮事件循环了。
  • 执行宏任务六输出11,执行宏任务七输出12。

 案例2

setTimeout(function () {
  console.log('9')
}, 0)
console.log('1')
async function async1() {
  console.log('2')
  await async2()
  console.log('8')
}
async function async2() {
  return new Promise(function (resolve) {
    console.log('3')
    resolve()
  }).then(function () {
    console.log('6')
  })
}
async1()

new Promise(function (resolve) {
  console.log('4')
  resolve()
}).then(function () {
  console.log('7')
})
console.log('5')
  • 先输出1,2,3。3后面的then进入微任务队列。
  • 执行外面的同步代码,输出4,5。4后面的then进入微任务队列。
  • 接下来执行微任务,因为3后面的then先进入,所以按序输出6,7。
  • 下面回到async1函数,await关键字等到了结果继续往下执行。
  • 输出8,进行下一轮事件循环也就是宏任务二,输出9。

参考:

https://juejin.im/post/5c148ec8e51d4576e83fd836

https://blog.csdn.net/j2IaYU7Y/article/details/81623516

http://es6.ruanyifeng.com/#docs/async

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值