首页 > 编程语言 >js异步编程,eventLoop,消息队列,宏任务,微任务

js异步编程,eventLoop,消息队列,宏任务,微任务

时间:2022-10-25 13:11:07浏览次数:54  
标签:异步 console log 队列 eventLoop js 任务

1.单线程的JavaScript   

JavaScript是一门单线程语言,起因是设计之初js只用来操作dom,对表单进行简单的校验。在这种执行环境简单的情况下,自然就选择了单线程来处理程序。但是单线程如果遇到执行时间较长的程序片段,会拖延甚至阻塞程序的执行,对于用户来说,页面呈现"卡死状态",这是最糟糕的体验。

​ 为了解决上述问题,JavaScript将程序的执行分为同步和异步。

在JavaScript中写异步代码也叫做异步编程,进行异步编程的方式有:

  • 回调函数

  • 事件监听

  • 发布订阅

  • promise

维护异步任务和执行异步任务

异步即将来, 异步任务就是将来执行的任务

js引擎是单线程的,那么异步任务是如何维护的呢?

js引擎负责解析并编译js代码。制定作用域标准,分配内存,创建执行上下文调用栈...。编译好的代码放到运行环境中去运行,而运行环境会维护异步任务。

对浏览器而言,浏览器是多线程的,它可以分配线程去倒计时定时器,发送请求,事件监听等。当定时器中的事件倒计时完毕,将其扔到也是由浏览器维护的消息队列中,当遇到其他异步时,浏览器会分配进程去处理,处理完毕也是扔到消息队列中。等待js引擎去执行。

以上所说的异步任务均是宏任务。

关于异步还有一些有趣的事情。

「有趣的异步控制台」

console也并非js标准,没有具体的约束和规则去指定console的行为,console的行为是由运行环境决定的。

摘自你不知道的JavaScript(中卷) p141

不同的浏览器和 JavaScript 环境可以按照自己的意愿来实现,有时候这会引起混淆。 尤其要提出的是,在某些条件下,某些浏览器的 console.log(..) 并不会把传入的内容立 即输出。出现这种情况的主要原因是,在许多程序(不只是 JavaScript)中,I/O 是非常低 速的阻塞部分。所以,(从页面 /UI 的角度来说)浏览器在后台异步处理控制台 I/O 能够提 高性能,这时用户甚至可能根本意识不到其发生。

console通常是进行程序调试写的比较多,如果产生了一些迷惑性行为,可以这样做

最好的选择是在 JavaScript 调试器中使用断点, 而不要依赖控制台输出。次优的方案是把对象序列化到一个字符串中,以强制执行一次“快照”,比如通过 JSON.stringify(..)。

当检测到js主线程中的调用栈为空时(主线程会维护一个巨大的匿名函数,这个匿名函数用来执行js代码)。 浏览器早已提供好了用作事件触发的线程,事件触发线程从消息队列中按照队列排序取出一个任务放到执行栈中压栈执行。

执行过程中遇到的问题:

  1. 如果遇到宏任务: 将其给浏览器进行处理,处理完毕放入消息队列中排队。

  2. 如果遇到微任务:将其放到微任务队列中,依次执行,不用去排队。也就是微任务是可以"插队"的。等到微任务队列中的所有微任务全部执行完毕。才会开启下一轮事件循环。

 
  • 微任务的出现让js的异步处理更加灵活,高效。
  • 例如修改dom: 如果在微任务中修改dom,则在这次事件循环中就可以看到修改后的结果,如果在宏任务中修改,则只能在下次事件循环中看到修改后的结果了。
  • 微任务有微任务消息队列,宏任务有宏任务消息队列[事件队列存放的是异步事件返回结果],但是js的事件循环是唯一一个。
宏任务和微任务有哪些?

宏任务有: scriptsetTimeoutsetIntervalsetImmediate(浏览器暂时不支持,只有IE10支持)、I/OUI Rendering

微任务有: Process.nextTick(node)PromiseMutationObserver

模拟执行一个宏任务

setTimeout(() => {
    console.log('setTimeout');
}, 0);
复制代码

模拟执行一个微任务

queueMicrotask(() => {
    console.log('queueMicrotask');
}); 
复制代码

上面两种方式不会创建额外的对象,不会造成浪费(比如通过promise

创建微任务.)

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')

复制代码
一道面试题

js编译完成,进入浏览器执行环境开始执行。

遇到async1,async2函数分配内存

打印script start

遇到setTimeout,计时完成放到消息队列中,等待主线程空闲时执行。

调用async1函数,打印async1 start 遇到awiait,同步代码,执行后面的async2函数,打印async2(async await是generator的语法糖。可以用generator来实现async await的效果。generator也是微任务队列) 将后面的片段放到微任务队列中。

创建Promise实例对象,打印promise1, 将then函数扔到微任务队列中。

打印script end

主线程空闲, 事件触发线程拿到微任务队列中的第一个任务,放到主线程中的调用栈中执行,打印async1 end

然后执行微任务队列中的第二个微任务,打印promise2,微任务队列清空,去宏任务队列中拿到第一个任务,放到主线程中执行,打印 setTimeout

标签:异步,console,log,队列,eventLoop,js,任务
From: https://www.cnblogs.com/qFire/p/16824509.html

相关文章

  • Node.js实现大文件断点续传
    前言平常业务需求:上传图片、Excel等,毕竟几M的大小可以很快就上传到服务器。针对于上传视频等大文件几百M或者几G的大小,就需要等待比较长的时间。这就产生了对应的解决方......
  • mockJS与file-saver依赖的冲突问题
    今天在使用POST下载并使用file-saver中的saveAs保存文件时意外地发现保存下来的文件直接报错说文件损坏,如下图Excel为例:网上查阅大量方法,经过切换后端服务器,改为上线项目......
  • Nodejs+Redis实现简易消息队列
    前言消息队列是存储数据的一个中间件,可以理解为一个容器。生产者生产消息投递到队列中,消费者可以拉取消息进行消费,如果消费者目前没有消费的打算,则消息队列会保留消息,直......
  • JS 中为什么要有 Iterator,JS 中数组,对象,Map,Set遍历的推荐方法
    JavaScript原有的表示“集合”的数据结构主要是数组(Array)和对象(Object),ES6又添加了Map和Set。这样就有了4种数据集合,用户还可以组合使用它们,定义自己的数据......
  • PO同步异步桥
    同步异步桥模式的PO接口大致流程为:发送端异步发送,接收端同步接收,接收端异步返回,发送端异步接收ESR注意点: 注意:接收端的inbound方向的SI的response的MT与outboun......
  • Gin-JSON,ProtoBuf渲染
    1.输出json和protobuf新建user.proto文件 syntax="proto3";optiongo_package=".;proto";messageTeacher{stringname=1;repeatedstringcour......
  • 创建一个json-server服务器
    json-server官网https://www.npmjs.com/package/json-server#getting-started1全局安装json-servernpminstall-gjson-server2创建json文件存储数据//db.......
  • 我把一个json格式的数据读到dataframe里面了 怎么解析出自己需要的字段呢?
    大家好,我是皮皮。一、前言前几天在Python最强王者交流群【WYM】问了一个pandas处理的问题,提问截图如下:原始数据如下图所示:后来还提供了一个小文件。二、实现过程......
  • BZOJ 1013([JSOI2008]球形空间产生器sphere-gauss消元练习)
    1013:[JSOI2008]球形空间产生器sphereTimeLimit: 1Sec  MemoryLimit: 162MBSubmit: 1181  Solved: 654[​​Submit​​][​​Status​​][​​Discu......
  • mongodb for Linq(T)操作和Json操作BsonDocument
    usingMongoDB.Driver;usingMongoDB.Driver.Linq;usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Linq.Expressions;usingSystem.Text;......