微任務
在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
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/502338.html
標籤:其他
上一篇:【面試題】JSON.stringify()妙用,你真的知道嗎?
下一篇:js上傳圖片裁剪
