在游戏设计中,"微任务"和"宏任务"是两种不同的任务类型。

微任务和宏任务具体有哪些-微任务和宏任务

"微任务"是指在游戏中可以立即完成的任务,通常需要花费较少的时间和精力。例如,打败一个简单的怪物、找到某个物品或开启某个门等。这些任务对游戏的推动具有重要作用,但是它们本身其实不会对全部游戏世界产生太大的影响。

"宏任务"则是指游戏中需要花费更多时间才能完成的任务,通常触及到多个步骤或复杂的剧情。例如,解锁新的区域、完成主线任务或挑战世界 boss 等。这些任务对游戏的世界观构建和角色的发展具有重要的作用,由于它们会对游戏的整体进程产生深远的影响。

在游戏中,微任务和宏任务通常是相互依存的。玩家可以通过完成微任务来取得必要的资源和经验,以便能够完成宏任务。同时,宏任务也为玩家提供了一个更加深入的游戏体验,使他们在探索游戏世界的同时也能够理解游戏的故事线和规则。

宏任务和微任务的区别

微任务和宏任务主要区别在于他们的执行顺序,Event Loop的走向和取值。

宏任务和微任务皆为异步任务,它们都属于一个队列。宏任务当前调用栈中执行的代码成为宏任务(主代码,定时器等等)。微任务 当前(此次事件循环中)宏任务执行完,在下一个宏任务开始之前需要执行的任务,可以理解为回调事件。宏任务中的事件放在callback queue中,由事件触发线程维护;微任务的事件放在微任务队列中,由js引擎线程维护。

在执行栈中执行一个宏任务,执行过程中遇到微任务,将微任务添加到微任务队列中。当前宏任务执行完毕,立即执行微任务队列中的任务。当前微任务队列中的任务执行完毕,检查渲染,GUI线程接管渲染。渲染完毕后,js线程接管,开启下一次事件循环,执行下一次宏任务(事件队列中取)。

异步任务定义

说到异步任务,我们第一时间想到的是多线程,我们常说的多线程问题,一般是指线程并发问题和数据同步问题。而异步任务属于多线程编程的一个环节主线程在继续当前任务的同时,创建一个或多个新的非阻塞线程去执行其他任务。

当主流程外需要执行1个或多个复杂计算,为了保障执行效率,可以使用异步任务。异步任务的主要作用是最大程度地使用服务器的性能,提升程序的响应速度。无需获取响应结果的简单异步如消息通知,需要响应结果的异步如商品信息查询。

在网上也看了不少关于javascript事件循环的文章,多数是以浏览器事件循环与nodejs中事件循环做对比,分析两种环境的差异。下面说的内容是浏览器事件循环与前端性能之间的关系,了解之后在开发中规避一些性能问题。以下所探讨的事件循环皆指浏览器的事件循环,本文属于个人理解,如有不对欢迎提点。

提到事件循环,相信现在多数前端小白并不陌生了。首先事件循环分为宏任务和微任务。

宏任务鼠标事件,键盘事件,网络事件,Html解析,定时器等;

微任务Dom变化,Promise;

当这些事件发生的时候浏览器会在对应的事件队列(宏任务队列和微任务队列)中添加该事件处理器(回调函数)等待执行。而事件循环是一直循环着看事件队列中是否还有未处理的处理器,如果有的话就从队列首位取出处理器执行,执行完之后就移除对应处理器,就是这样一直循环着直到浏览器关闭为止,即使事件队列为空!但是在处理宏任务队列和微任务队列的方式不同。

在一次事件循环中只能处理一个宏任务,而需要处理所有微任务直到微任务队列清空

说明事件循环是在主程序执行完之后就开始循环执行事件,主程序说简单点就是一个js文件从第一行执行到最后一行,主程序结束(此处说的是该应用就一个js文件)

举一个生活中的例子

银行中排队办理业务的时候,假设每个排队等待办理的普通客户是宏任务,而VIP客户是微任务。那么在银行早上开始上班的之前,柜员启动相应的机器(电脑,打印机等)属于主程序,等一切准备好之后就开始办理业务了。假如现在有10个普通用户(宏任务)在等待,开始处理第一个客户,处理完之后叫号第二个客户,开始处理。如果在处理第二个客户的时候突然来个一个vip用户,那么在处理为完普通用户之后就轮到处理VIP用户(微任务),如果在处理VIP用户的时候又来了个VIP用户的话3号普通客户就得等待处理完两个VIP客户。当然此处举例皆是只该银行就一个服务窗口,复合js单线程模式。

下图是一个完整的事件循环图

浏览器通常会尝试60秒渲染一次页面,以达到每秒60帧(60fps)的速度, 60fps是检验前端体验是否流畅的标准,在动画里就意味着当浏览器没16ms一次刷新的话,体验是最流畅的,所有在整个页面生命周期中每一次事件循环都应该在16ms内完成。

但是在事件循环中可能会处理比较耗时的任务,那么渲染就会延后这样就会导致动画看上去不流畅,更严重的可能是页面处于假死状态等影响用户体验。

如果加上UI渲染的话上面的事件循环图是这样的

上面提到浏览器会尝试16ms重新渲染页面,那么假如在处理事件的时候遇到耗时任务的时候,浏览器将会延迟渲染页面,如果处理不当那将会导致体验差问题。接下来仔细分析以下整个流程。

首先先排除为任务,只有宏任务的程序。现在有两个点击事件

假如主线程运行需要15ms,btn1事件处理器完成需要8ms, btn2需要10ms;那么整个流程是这样

假如用户点击速度很快的时候,主线程运行期间在5ms和12ms时候分别点击了btn1,btn2按钮,触发点击事件,此时因为还处与主线程运行时间内,所有此时会向宏任务队列添加两个事件任务。当主线程运行到15ms时结束,此时浏览器可以重新渲染。渲染完之后进入事件循环,首先从任务队列中取出任务btn1事件处理器执行,此过程会耗时8ms,处理完之后结束一次事件循环,并移除事件处理器btn1。此时浏览器可以重新渲染,渲染完之后又进行到第二次事件循环,重复上述步骤,直到事件队列清空为止。

如果事件循环中存在为任务的话流程如下

其实只是在宏任务之后加入了一个时间段处理为任务.。在第一循环中处理btn1事件处理器时添加promise1到微任务队列中,在执行完btn1事件之后检查微任务队列发现有一个任务待处理,然后取出处理之后移除微任务promise1在循环微任务队列,发现以微任务队列为空,28ms时浏览器可以重新渲染(此时浏览器距离上次渲染相差12ms,渲染流畅)。在执行第二次事件循环的时候,在执行到微任务队列时,需要处理两个任务,耗时8ms,46ms时浏览器可以重新渲染(此时浏览器距离上次渲染相差18ms,渲染流畅)。

如果在事件循环中有的任务比较耗时,会导致浏览器渲染fps变小,从而导致用户体验差。如向页面中插入10000个td节点的时候,如果是一次循环就appendChild一次,那相当于总共会有10000个微任务待执行,这样就会影响到浏览器渲染的fps,所有会出现点击页面没有反响的体验,这就是为什么插入多个节点需要拼接到一起一次性插入节点。了解事件循环和浏览器渲染之间到联系之后,以后开发多注意一些耗时任务到处理,到此分享结束。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。