首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >宏观任务和微任务练习

宏观任务和微任务练习
EN

Stack Overflow用户
提问于 2021-04-01 00:48:10
回答 1查看 113关注 0票数 1

关于在Google中运行的微任务和宏任务,我有以下问题。请参阅下一个示例(杰克·阿奇博尔德提出了以下代码):

代码语言:javascript
复制
// Let's get hold of those elements
var outer = document.querySelector('.outer');
var inner = document.querySelector('.inner');

// Let's listen for attribute changes on the
// outer element
new MutationObserver(function () {
  console.log('mutate');
}).observe(outer, {
  attributes: true,
});

// Here's a click listener…
function onClick() {
  console.log('click');

  setTimeout(function () {
    console.log('timeout');
  }, 0);

  Promise.resolve().then(function () {
    console.log('promise');
  });

  outer.setAttribute('data-random', Math.random());
}

// …which we'll attach to both elements
inner.addEventListener('click', onClick);
outer.addEventListener('click', onClick);

inner.click();

如果运行以下代码,则日志的顺序为:

代码语言:javascript
复制
click
click
promise
mutate
promise
timeout
timeout

这里发生了两个我不明白的问题,因为我都有一个模糊的想法。

  1. 如果调用inner.click()一次,为什么单击是打印两次?我认为这是因为点击内部也使点击外部,但我不确定。
  2. 为什么只变异一次?这对我来说很有意义,因为在第二次迭代中,它已经发生了变异,因此不会触发回调。

我对其中任何一个都不确定。

有什么想法吗?谢谢,曼纽尔

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-04-01 00:55:34

如果调用inner.click()一次,为什么单击是打印两次?我认为这是因为点击内部也使点击外部,但我不确定。

是的-这是因为单击事件向上传播到包含元素。除非对事件调用stopPropagation,否则它将触发事件被发送到的元素(此处为inner)和根元素之间的所有侦听器。outerinner的容器,所以点击内部就可以在传播过程中到达外部。

为什么只变异一次?这对我来说很有意义,因为在第二次迭代中,它已经发生了变异,因此不会触发回调。

因为DOM的两个突变都是同步执行的,所以当在两个单击侦听器中调用setAttribute时,观察者只在所有侦听器任务完成之后才运行。

两个突变都可以在突变列表中看到(传递给MutationObserver回调的数组):

代码语言:javascript
复制
// Let's get hold of those elements
var outer = document.querySelector('.outer');
var inner = document.querySelector('.inner');

// Let's listen for attribute changes on the
// outer element
new MutationObserver(function (mutations) {
  console.log('mutate');
  for (const mutation of mutations) {
    console.log('change detected on attribute', mutation.attributeName);
  }
}).observe(outer, {
  attributes: true,
});

// Here's a click listener…
function onClick() {
  console.log('click');

  setTimeout(function () {
    console.log('timeout');
  }, 0);

  Promise.resolve().then(function () {
    console.log('promise');
  });

  outer.setAttribute('data-random', Math.random());
}

// …which we'll attach to both elements
inner.addEventListener('click', onClick);
outer.addEventListener('click', onClick);

inner.click();
代码语言:javascript
复制
<div class="outer">
  <div class="inner">
    click
  </div>
</div>

出于类似的原因:

代码语言:javascript
复制
elm.className = 'foo';
elm.className = 'bar';

只会在elm上触发一次观察员。

相比之下,

代码语言:javascript
复制
elm.className = 'foo';
setTimeout(() => {
  elm.className = 'bar';
});

(或者代码中实现的相同类型的东西)将导致观察者触发两次,因为超时是一个宏任务,观察者回调以microtask的形式运行。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66897075

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档