我在浏览器控制台中输入此代码:
document.body.addEventListener(
"click",
() => {
Promise.resolve().then(() => console.log(1));
console.log(2);
},
false
);
document.body.addEventListener(
"click",
() => {
Promise.resolve().then(() => console.log(3));
console.log(4);
},
false
);
这两个事件监听器监听点击事件并打印数字。
然后我写了一行来执行这个语句:
document.body.click();
符合我的期望,结果是:
2
4
1
3
但是,然后,我单击屏幕,事件回调被触发,结果如下:
2
1
4
3
为什么点击屏幕并手动执行
body.click()
会产生不同的结果?
单击与通过代码运行它看到不同结果的原因是异步操作的运行方式,尤其是 Promise。
当您手动单击屏幕时,附加到 body 元素的单击事件的事件侦听器将按照它们在代码中添加的顺序触发。 在这种情况下,第一个监听器执行,记录 2,然后记录 1,然后第二个监听器执行,分别记录 4 和 3。
2
1
4
3
运行 document.body.click(): 当您执行 document.body.click() 时,会以编程方式触发 click 事件,但由于您还使用了 Promise (Promise.resolve().then(...)),因此行为略有不同。
附加到点击事件的事件监听器仍然按照添加的顺序执行。 但是,由于 Promise,它们内部的回调(记录 1、2、3、4)可能不会立即执行,因为它们在微任务队列中排队。 这意味着,虽然在调用 document.body.click() 时立即触发 click 事件,但事件侦听器内的 Promise 会异步解析,并且稍后执行它们的回调(console.log 语句)。 因此,Promise 的异步性质导致手动点击和程序化点击之间的时间差异,从而导致记录数字的顺序不同。
我建议检查一下:微任务和承诺