微任务

在js中,当使用promise,会将当前任务加入事件执行的微任务队列,有且只有这一种方法可以,因为当使用了promise,在JS引擎中会触发VM::queueMicrotask,会向m_microtaskQueue队列中压入事件,在V8中只有这一种暴露方式,没有其他接口可以调用这个方法

void VM::queueMicrotask(JSGlobalObject& globalObject, Ref<Microtask>&& task)
{
m_microtaskQueue.append(makeUnique<QueuedTask>(*this, &globalObject, WTFMove(task)));
}

然后会执行VM::drainMicrotask,只要m_microtaskQueue不为空就会一直取微任务队列第一个去执行

void VM::drainMicrotasks()
{
do {
while (!m_microtaskQueue.isEmpty()) {
m_microtaskQueue.takeFirst()->run();
if (m_onEachMicrotaskTick)
m_onEachMicrotaskTick(*this);
}
didExhaustMicrotaskQueue();
} while (!m_microtaskQueue.isEmpty());
finalizeSynchronousJSExecution();
}

所以Promise会将事件放到微任务队列的最后一位,然后继续执行,如果promise嵌套,内层的promise也会被放到微任务队列的最末尾,然后执行的时候再将其中的任务放到队列的末尾

宏任务

但是相比于微任务是js-core中自带的基础设施,js-core源代码中是不包含宏任务相关内容的,对于宏任务的相关内容是在C++的js引擎中实现的,单个js代码是通过语句是通过evaluateScript进行执行,而宏任务的实现相当于在C++中通过循环来去执行多个evaluateScript方法,而每个evaluateScript在执行前都有lock保证队列已经清空

下面是宏任务实现的伪代码

// 初始化JS的执行环境
JSContext* context = [[JSContext alloc] init];
// 初始化C++环境的宏任务队列
NSMutableArray * macroTaskQueue = [[NSMutableArray alloc] init];
// 创建微任务锁
NSConditionLock* condLock = [[NSConditionLock alloc] initWithCondition:0]; // 引入js中的console.log方法,并转换为NSlog输出
context[@"console"] = [JSValue valueWithNewObjectInContext:context];
context[@"console"][@"log"] = ^(JSValue* s) {
NSLog(@"%@", [s toString]);
}; // 引入setTimeout方法
context[@"setTimeout"] = ^(JSValue* f, JSValue* duration) {
NSThread* timer = [[NSThread alloc]initWithBlock:^{
[NSThread sleepForTimeInterval:[duration toDouble] / 1000]; // 休眠1秒 [condLock lock]; // 使用锁 [macroTaskQueue addObject:f]; // 将任务的压入引擎宏任务队列 [condLock unlockWithCondition:1]; 将微任务锁设置为1
//[f callWithArguments:@[]];
}];
[timer start];
}; NSThread* scanner = [[NSThread alloc]initWithBlock:^{
char sourceCode[1024];
while(scanf("%[^\n]", sourceCode) != -1) {
getchar();
[condLock lock]; [macroTaskQueue addObject:[NSString stringWithUTF8String: sourceCode]]; [condLock unlockWithCondition:1];
}
}];
[scanner start]; while(true) { //Event Loop
[condLock lockWhenCondition:1]; // 将锁设置位1
for (id task in macroTaskQueue){
if([task isKindOfClass:JSValue.class])
[task callWithArguments:@[]];
if([task isKindOfClass:NSString.class]) {
JSValue* result = [context evaluateScript:task]; // 执行js内容
NSLog(@"%@", [result toString]);
}
}
[macroTaskQueue removeAllObjects]; // 将宏任务队列清空
[condLock unlockWithCondition:0]; // 将锁设置位0
}

事件循环:微任务和宏任务在v8中实现的简单理解的更多相关文章

  1. javascript事件环微任务和宏任务队列原理

    哈喽!大家好!我是木瓜太香,我又来嘞,今天来说说前端面试中经常别问到的 JS 事件环问题. JS 事件环 JS 程序的运行是离不开事件环机制的,这个机制保证在发生某些事情的时候我们有机会执行一个我们事 ...

  2. js的事件循环机制:同步与异步任务(setTimeout,setInterval)宏任务,微任务(Promise,process.nextTick)

    javascript是单线程,一切javascript版的"多线程"都是用单线程模拟出来的,通过事件循环(event loop)实现的异步. javascript事件循环 事件循环 ...

  3. 事件循环 EventLoop(Promise,setTimeOut,async/await执行顺序)

    什么是事件循环?想要了解什么是事件循环就要从js的工作原理开始说起: JS主要的特点就是单线程,所谓单线程就是进程中只有一个线程在运行. 为什么JS是单线程的而不是多线程的呢? JS的主要用途就是与用 ...

  4. 深入理解JavaScript的事件循环(Event Loop)

    一.什么是事件循环 JS的代码执行是基于一种事件循环的机制,之所以称作事件循环,MDN给出的解释为 因为它经常被用于类似如下的方式来实现 while (queue.waitForMessage()) ...

  5. 浅谈 Event loop (事件循环)

    从Event Loop谈JS的运行机制 先来理解一个概念: JS分为同步任务和异步任务 同步任务都在主线程上执行,形成一个执行栈 Execute Content Stack 主线程之外,事件触发线程管 ...

  6. js的事件循环机制和任务队列

    上篇讲异步的时候,提到了同步队列和异步队列的说法,其实只是一种形象的称呼,分别代表主线程中的任务和任务队列中的任务,那么此篇我们就来详细探讨这两者. 一.来张图感受一下 如果看完觉得一脸懵逼,请继续往 ...

  7. JavaScript专题之事件循环

    准备知识 1. 进程(process) 进程是系统资源分配一个独立单位,一个程序至少有一个进程.比方说:一个工厂代表一个 CPU, 一个车间就是一个进程,任一时刻,只能有一个进程在运行,其他进程处于非 ...

  8. 浏览器中的JavaScript事件循环机制

    浏览器的事件循环机制是HTML中定义的规范. JavaScript有一个主线程和调用栈,所有的任务都会被放到调用栈等待主线程执行. JS调用栈 是一种先进后出的数据结构.当函数被调用时,会被添加到栈中 ...

  9. JS浏览器事件循环机制

    文章来自我的 github 博客,包括技术输出和学习笔记,欢迎star. 先来明白些概念性内容. 进程.线程 进程是系统分配的独立资源,是 CPU 资源分配的基本单位,进程是由一个或者多个线程组成的. ...

随机推荐

  1. CentOS查看操作系统安装时间信息:

    CentOS查看系统安装时间信息: 方法1:[root@logserver ~]#  ll /boot/|egrep -i "(grub|lost\+found)" 方法2:[ro ...

  2. Android Studio的初次认识

    Android的初试 一.认识Android Studio 在我们新建项目的时候,会遇到这样的一个窗口,首先我们认识一下这些都是什么,这样我们才能够更好的进行下一步的学习! 这里的 Phone and ...

  3. 图扑 Web 可视化引擎在仿真分析领域的应用

    ​ 前言 在数字孪生和仿真研究过程中,会产生大量和三维空间相关的数值信息,比如设备外观的扫描数据.地形扫描数据.生产设备温度场/压力场.流体的速度场.流体扩散,以及各种仿真数据:速度,压力,应力,温度 ...

  4. Linux 任务计划管理

    在某个时间点执行一次任务 at工具 作用:用于执行一次性任务,需要指定执行的时间. at工具来源于at软件包. 依赖与atd服务,需要启动才能实现at任务.#通过这个守护进程见监控at的相关内容 #选 ...

  5. 基于ABP实现DDD--聚合和聚合根实践

      在下面的例子中涉及Repository.Issue.Label.User这4个聚合根,接下来以Issue聚合为例进行分析,其中Issue聚合是由Issue[聚合根].Comment[实体].Iss ...

  6. day10 Map_查找与遍历

    Map 查找表 Map体现的结构是一个多行两列的表格,其中左列称为key,右列称为value. Map总是成对保存数据,并且总是根据key获取对应的value.因此我们可以将查询的条件作为key查询对 ...

  7. PLC转OPC UA的协议转换网关需要多少钱呢?

    嵌入式OPC UA网关BL102简化了OPC UA程序的开发与IIOT工业物联网应用 在制造业数字化升级过程中,我们碰到最多的工作便是针对每一款PLC去开发一套OPC UA程序,然后通过这套程序去读取 ...

  8. 技术分享 | innodb_buffer_pool_size为什么无法调低至1GB以内

    前言 innodb_buffer_pool_size可以调大,却不能调小至1GB以内,这是为什么? MySQL 版本:5.7.30 测试环境有台 MySQL 服务器反应很慢,检查系统后发现内存使用量已 ...

  9. Docker 09 可视化

    参考源 https://www.bilibili.com/video/BV1og4y1q7M4?spm_id_from=333.999.0.0 https://www.bilibili.com/vid ...

  10. mongo数据库-mongo角色权限

    Built-In Roles(内置角色): 1. 数据库用户角色:read.readWrite; 2. 数据库管理角色:dbAdmin.dbOwner.userAdmin: 3. 集群管理角色:clu ...