当前位置: 首页 > Web前端 > HTML

JS任务机制-springboot实战电商项目mall4j

时间:2023-03-28 01:20:18 HTML

springboot实战电商项目mall4j(https://gitee.com/gz-yami/mall4j)java商城系统源码1.介绍工作while,今天就总结到这里,让我们来看看浏览器执行JS任务的机制。在日常工作中,我做的最多的两件事是1.为设计图编写HTMLCSS2.对接口请求的数据进行页面渲染处理返回数据会涉及到异步函数,以及JS执行代码时,它会先执行同步任务,再执行异步任务。此时,如果需要使用异步任务中的值来执行同步任务,则会抛出错误。为什么会这样,让我们??从基础开始。2.浏览器内核浏览器内核是多线程的。具体有哪些如下图所示?##2.1GUI渲染线程主要负责HTML、CSS的渲染和解析,构建DOM树。当对HTML标签执行v-ifv-show等操作时,会触发界面的重绘和重排,线程会在此时执行。JS引擎在执行的时候,会处于休眠状态,会被放到另一个任务队列中。当JS对DOM、CSS等进行操作时,会保持更新状态,等待JS引擎空闲,立即执行。2.2JS引擎线程主要负责处理JavaScript脚本程序。当JS引擎处理完主线程的任务后,会等待任务队列中的任务到来,直到没有任务可执行。这时候就会涉及到一个问题,因为JS可以操作Dom,所以可能会出现渲染错误的一系列问题,所以浏览器不允许GUI线程同时执行,它会等到JS线程被执行,执行过程中的GUI更新会被保存起来。2.3异步http请求线程在进行网络请求时,会开启一个新的进程,防止JS引擎的执行被阻塞。当状态发生变化时,会从任务队列传回JS主线程。如果请求结果是400、200,这些状态2.4定时器在线程的JS代码中触发setTimeout和setInterval。为了不影响这两个定时器在触发时的准确性,浏览器也会另开一个线程来放置它。计时结束后,先放到事件线程中,JS引擎空闲时再执行2.5事件触发线程。当JS中的click、touch等事件触发线程时,该事件会被添加到待处理队列的末尾,等待JS引擎的处理。3、宏任务和微任务是相对于浏览器而言多线程的JS引擎是单线程的,历史原因就不细说了。因为是单线程,JS从上往下执行代码的时候,会有HTTP请求,定时器等,不可能等到它们执行完了再进行下一步,影响用户经验。这时候就需要任务队列的帮助了,我在下面画了一张图方便理解。主线程的任务执行时,会查询任务队列中是否有可执行的任务。如果有,就会拉到主进程去执行。如果任务队列中没有任务,它将停止。上图中我画了两个任务队列,是因为JS中有宏任务和微任务两种。宏任务执行完后,微任务就会执行。微任务执行完后,会执行宏任务,主线程算作一个宏任务。task,所以当主线程的task执行的时候,会从microtask中检查有没有task可以执行,如果没有task,就会去macrotask中找。最常见的两个宏任务是setTimeout和setInterval(主线程也是宏任务),而最常见的微任务是Promise.then()中的内容。setTimeout(()=>{console.log('macrotask')},500)Promise.resolve().then(value=>{console.log('microtask')})console.log('已经在mainprocess,thetasktobeexecuted')JS任务执行是先执行微任务,主流程任务执行完再执行宏任务,所以不管你宏任务的timer设置多快,都得等直到主任务和微任务都执行完了就轮到你去做了。setTimeout(()=>{console.log('等到花儿散了')},5)Promise.resolve().then(value=>{for(vari=0;i<999999999;i++){console.log('等我跑完')}})console.log('我跑完了')当然,定时器不会等到同步任务执行完才开始计时。上面提到的定时器触发线程就是为此准备的。当代码执行到定时器时,会抛给定时器线程进行计时。计时完成后,会根据速度依次放入宏任务队列中。同时会依次执行。.setTimeout(()=>{console.log('明明是我先进去的')},1000)setTimeout(()=>{console.log('谁让我比你走得快')},500)console.log('Waitandwait')我喜欢考的面试题之一就是promise中嵌套的setTimeout。请记住,不要害怕setTimeout中的嵌套承诺。当主线程中没有任务执行时,会先去微任务队列。任务被一个一个地找到并执行。所有微任务执行完毕后,会在宏任务中搜索任务执行。即使在微任务中发现了定时器等宏任务,也会被放到其他任务队列中,在这里等待。执行队列后执行。调用宏任务或微任务时共享主线程中声明的全局变量。即使定时器时间相等,也会按顺序显示。vara=0for(vari=0;i<100;i++){setTimeout(()=>{console.log(++a)},1000)}当然,如果我们只需要考虑这些任务队列,但是当我们处理这些数据需要将它们渲染到页面时,就会有另一种情况,浏览器决定了渲染刷新的频率。这个频率通常与用户的显示速率有关。如果是60hz,每秒会刷新60次,因为每秒渲染的次数是固定的,但是一旦执行一个任务,就会有上千个CSS变化影响下一次渲染,进程上的任务会按顺序执行,但它们在渲染每一帧时不会按顺序出现,因为模块移动得越来越快,屏幕飞溅。所以写代码的时候可以调用回调函数requestAnimationFrame来限制,functioncallback(){moveBox()//改变css样式functionreuquestAnimationFrame(callback)}//稳步前进functioncallback(){moveBox()//改变cssStylefunctionsetTimeout(callback,100)}//越来越快splashscreenjs在执行任务时遇到代码错误会阻塞不行,会出现页面卡住,点击无响应的情况。4.PromisePromise在解决回调地狱和简化我们的代码方面起到了很大的作用。Promise有三种状态,pending等待,另外两种是resolvedecision和rejectrejection。如果最初创建promise实例时没有发送通知,则后面的.then()中的代码将不会被执行。newPromise((resolve,reject)=>{console.log()//必须有resolve()或reject()其中之一}).then(value=>{console.log("waiting")})//满足条件后,.then()中的执行代码会被送到微任务队列中。这时候promis的状态就不能再改变了。springboot实战电商项目mall4j(https://gitee.com/gz-yami/mall4j)java商城系统源码