微任务

在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
}

最新文章

  1. webpack -p压缩打包react报语法错误处理
  2. input上下居中问题
  3. hdu 4055 &amp;&amp; hdu 4489 动态规划
  4. OpenGL的GLUT注册回调函数[转]
  5. XAMPP启动mysql遇到的问题
  6. 函数lock_rec_get_n_bits
  7. Codeforces Gym 100463A Crossings 逆序数
  8. 用js生成下载文件
  9. Course Schedule II 解答
  10. tnsping慢的问题解决
  11. 每天4亿行SQLite订单大数据测试(源码)
  12. Gson解析空字符串异常的处理
  13. 属性动画QPropertyAnimation
  14. dedecms首页去掉index.html怎么设置
  15. HTML标记 2 ——表格
  16. Kafka:ZK+Kafka+Spark Streaming集群环境搭建(十五)Spark编写UDF、UDAF、Agg函数
  17. (实用)Linux下Eclipse安装配置PyDev
  18. CSS实现各类分栏布局
  19. Tomcat 系统架构与设计模式2
  20. 微信小程序语音识别

热门文章

  1. NC14301 K-th Number
  2. 基于.NetCore开发博客项目 StarBlog - (14) 实现主题切换功能
  3. 当mysql表从压缩表变成普通表会发生什么
  4. zip格式文件编码检测
  5. go grpc: connection reset by peer 的一种解决方案
  6. SP96 SHOP-Shopping 题解
  7. 【机器学习基础】——另一个视角解释SVM
  8. 使用.NET简单实现一个Redis的高性能克隆版(三)
  9. eclipse mave无法下载jar包
  10. PerfView专题 (第一篇):如何寻找热点函数