gpt4 book ai didi

javascript - 说事件发生在我们开始倾听之前是什么意思?

转载 作者:行者123 更新时间:2023-11-29 19:10:23 24 4
gpt4 key购买 nike

在阅读 Javascript Promises 时,我看到一些博客/文章首先将 Promise 实现与 Javascript 事件模型进行比较,然后再与回调模式进行比较。

在与事件模型进行比较时,通常提到“事件可能在我们开始监听它们之前发生”或“您需要确保所有适当的事件处理程序在第一次事件发生之前添加'

我正在努力解决这个问题,但我不太确定从代码的 Angular 来看这怎么可能。在我们添加处理程序之前,事件如何发生?任何人都可以提供具体的例子来解释这一点吗?

最佳答案

他们的意思几乎就是字面意思:事件发生在我们开始监听它之前。例如,假设我们显示一个按钮,但在我们添加一个事件处理程序监听对该按钮的点击之前有两秒的延迟。如果用户在这两秒内点击,事件会在我们监听之前发生。

例子:

function run() {
// Show a button
document.getElementById("btn").style.display = "inline";

// Wait two seconds before we hook up a handler
setTimeout(function() {
document.getElementById("btn").addEventListener("click", function() {
console.log("Got a click");
}, false);
}, 2000);

// If the user clicks within those two seconds, the event happened
// before we were listening for it.
}

// This is just stuff to make sure the user is ready before showing the button
var counter = 4;
tick();

function tick() {
if (counter == 0) {
document.getElementById("get-ready").style.display = "none";
run();
} else {
document.getElementById("countdown").innerHTML = counter--;
setTimeout(tick, 1000);
}
}
<p id="get-ready">Get ready, a button will appear in <span id="countdown"></span>, click it as soon as it appears, then again a couple of seconds later:</p>
<input style="display: none" type="button" id="btn" value="Click me as soon as I appear, and again a couple of seconds later">

What I was looking for was some generic cases where events are fired before we attach listeners.

好吧,以上内容非常通用:考虑将 JavaScript 放在 script 中的通常做法标记在文档主体的末尾,就在结束之前 </body>标签,或使用 asyncdefer其上的属性。这意味着有一段很短的时间可以点击页面上的任何按钮,但我们还没有在它们上连接处理程序。例如,如果出现临时网络故障,加载您的 JavaScript 文件需要两秒而不是通常的 65 毫秒,您的用户会在您挂接处理程序(正在监听它)之前单击按钮(触发事件)。

或者,这曾经是一个很好的例子,但据我所知在现代浏览器上不再发生 Kaiido says它在 WebKit 浏览器上仍然有效,尽管我无法在 iOS Safari 上实现它:添加 img到文档并期望从这样的代码中获取加载事件:

var img = document.createElement("img");
img.src = "path/to/the/image.png";
img.addEventListener("load", function() {
// Handle the fact it loaded
}, false);
img.addEventListener("error", function() {
// Handle the fact it failed
}, false);
someOtherElement.appendChild(img);

从表面上看,由于 JavaScript 的 run-to-completion 语义以及默认情况下我们的 JavaScript 代码在单个 UI 线程上运行这一事实,似乎不存在竞争条件。但是那里 存在竞争条件,因为虽然我们的代码将遵循单线程,但浏览器 不是单线程的。所以这可能会发生:

  1. img.src = "path/to/the/image.png"; .
  2. 浏览器的资源管理代码去寻找图像。
  3. 资源管理在缓存中找到它,不需要重新验证,因此将图像数据与元素相关联并触发load。事件。
  4. 事件系统进入队列任务以回调任何load元素上存在的事件处理程序,未找到任何事件处理程序,也不对任何任务进行排队。
  5. 我们附加处理程序并附加元素。
  6. 我们的代码运行完成。
  7. 我们从来没有得到 loaderror事件回调。

相反,如果我们然后设置src :

var img = document.createElement("img");
img.addEventListener("load", function() {
// Handle the fact it loaded
}, false);
img.addEventListener("error", function() {
// Handle the fact it failed
}, false);
img.src = "path/to/the/image.png"; // <=== Moved
someOtherElement.appendChild(img);

然后同样的场景像这样上演:

  1. 我们附加我们的处理程序。
  2. img.src = "path/to/the/image.png"; .
  3. 浏览器的资源管理代码去寻找图像。
  4. 资源管理在缓存中找到它,不需要重新验证,因此将图像数据与元素相关联并触发load。事件。
  5. 事件系统进入队列任务以回调任何load元素上存在的事件处理程序。它会找到一个,因此会在任务队列下一次为空时将任务排队以调用它。
  6. 我们附加元素。
  7. 我们的代码运行完成。
  8. 任务循环从队列中取出下一个任务,恰好是我们的load。回调。
  9. 任务循环调用我们的回调。

现在,这种行为非常令人讨厌,现代浏览器不再这样做了(尽管 Kaiido says 它仍然在 WebKit 上这样做,我无法确认)。虽然我仍然像它一样编写代码(第二个示例),因为它可以,这是浏览器工作的有效方式。

关于javascript - 说事件发生在我们开始倾听之前是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39315372/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com