哪个任务setTimeout或click事件在任务队列中被优先排序?

如何解决哪个任务setTimeout或click事件在任务队列中被优先排序?

我正在学习执行堆栈,任务队列和事件循环机制。

我不断单击按钮,直到可用主线程(在完成函数a()之前)如下。
我以为click(UI)事件和setTimeout使用相同的队列,称为Macrotask或Task Queue,因此当我单击1s和3s之间的按钮时,我认为task2的日志打印在task1和task2之间。但是结果却并非如此。始终先打印Task2(单击事件),并在单击事件之后打印setTimeout事件(task1,task3)。

所以我想知道点击事件是否使用与setTimeout不同的队列机制,或者点击事件的优先级高于setTimeout。

预先感谢您的帮助

操作

  1. 单击按钮(任务2)
  2. -------- 1000毫秒setTimeout task1 --------
  3. 单击按钮(任务2)
  4. -------- 3000毫秒setTimeout task3 --------
  5. 单击按钮(任务2)
  6. -------- 6000ms主线程现已可用--------

我的期望日志订单

fn a done
task2 (click) done
task1 (setTimeout 1000ms) done
task2 (click) done
task3 (setTimeout 3000ms) done
task2 (click) done

结果日志顺序

fn a done
task2 (click) done
task2 (click) done
task2 (click) done
task1 (setTimeout 1000ms) done
task3 (setTimeout 3000ms) done

代码

const btn = document.querySelector('button');
btn.addEventListener('click',function task2() {
  console.log('task2 (click) done');
});

function a() {
  setTimeout(function task1() { 
    console.log('task1 (setTimeout 1000ms) done');
  },1000);

  setTimeout(function task3() { 
    console.log('task3 (setTimeout 3000ms) done');
  },3000);

  // hold main thread for 6000ms(*1)
  const startTime = new Date();
  while (new Date() - startTime < 6000);

  console.log('fn a done');
}

a();
<button>button</button>
<script src="main.js"></script>

解决方法

让我们看看您使用setTimeout和while循环正在做什么。

如果运行代码片段,您将看到1秒和3秒超时的时间戳基本上是相同的。这是因为while循环将主线程阻塞了6秒钟,直到可以运行setTimeout中的函数为止。

仅在主线程空闲时才在1秒或3秒后不完全执行回调。 setTimeout保证回调函数至少在x毫秒后执行,这对于任务1 >> 1秒,对于任务3> = 3秒。

kubectl delete pod coredns-f9fd979d6-sw2qp --namespace=kube-system

,

我认为click(UI)事件和setTimeout使用相同的队列

他们没有。

UI事件使用user interaction(UI) task source,它在大多数浏览器中都有自己的task-queuesetTimeout使用timer task-source,而在大多数浏览器中也都有自己的task-queue浏览器。

尽管规范没有要求,但UI任务源在几乎所有浏览器中的优先级是所有任务源中的最高之一,而计时器的优先级是最低的。

此优先级的工作方式是,在event-loop's processing model的第一步中,用户代理(UA)必须从其事件队列中选择一个将执行的 task 事件

注意:通俗地称为“宏任务” 是任何不是microtask的任务。
The microtask queue is not a task queue,虽然在事件循环处理的第一步中可以选择微任务作为主要任务,但微任务队列不能被优先排序,因为必须清空在每个microtask-checkpoints上同步 ,这在每次事件循环迭代中都可能发生多次,尤其是after the chosen task gets executed

因此,在这里,while循环完成后,阻塞了事件循环,并开始了下一次迭代,UA必须选择从哪个任务队列中选择下一个任务。 它将在其 UI任务队列中看到有新事件在等待,并执行它们,因为它们具有更高的优先级。
然后,当它们全部执行完毕后,它将选择 timers队列,并按照其计划时间执行它们。

还请注意they have饥饿系统,它会阻止高优先级的任务队列长时间阻止其他任务队列。


最后,我要提一个建议,让我们的Web开发人员直接处理所有这些优先事项:main thread scheduling

使用此实验功能,我们可以将代码段重写为

if( !("scheduler" in window) ) {
  console.error("Your browser doesn't support the postTask API");
  console.error("Try enabling the Experimental Web Platform features in chrome://flags");

}
else {
  scheduler.postTask(() => { 
    console.log('task1 (background) done');
  },{ priority: "background" } );

  scheduler.postTask(() => { 
    console.log('task2 (background) done');
  },{ priority: "background" } );

  // hold main thread for 6000ms(*1)
  const startTime = new Date();
  while (new Date() - startTime < 2000);
  scheduler.postTask(() => { 
    console.log('task3 (user-blocking) done');
  },{ priority: "user-blocking" } );

  console.log('synchronous done');
}

并看到最终任务首先执行。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?