在我们开始收听事件之前发生的事件是什么意思? [英] What is meant by saying that events happened before we started listening to them?
问题描述
在阅读Javascript Promises时,我遇到了一些博客/文章,其中Promise实现首先与Javascript Event模型进行比较,然后是回调模式。
While reading for Javascript Promises, I have come across few blogs/articles where the Promise implementation is first compared with the Javascript Event model and then the callback pattern.
在与事件模型进行比较时,通常会提到事件可能发生在我们开始侦听之前'或'您需要确保在之前添加所有适当的事件处理程序第一次发生事件'
While comparing with the Event model, it is commonly mentioned that 'it's possible that the events happened before we started listening for them' OR 'you need to ensure that all appropriate event handlers are added before the first time an event occurs'
我正在试图解决这个问题,而且我不太确定从代码角度来看这可能性如何。在添加处理程序之前,如何发生事件?任何人都可以提供具体的例子来解释这个吗?
I'm trying to wrap my head around this and I'm not quite sure howz that possible from code standpoint. How can an event occur before we add the handlers ? Can anyone provide concrete examples to explain this ?
推荐答案
他们的意思几乎就是他们所说的:事件发生在我们开始听之前为了它。例如,假设我们显示一个按钮,但是在我们添加一个事件处理程序监听该按钮的点击之前,有两秒钟的延迟。如果用户在这两秒内点击,则事件发生在我们收听之前。
They mean pretty much what they literally said: The event occurred before we started listening for it. For instance, suppose we show a button, but there's a delay of two seconds before we add an event handler listening for clicks on that button. If the user clicks within those two seconds, the event occurs before we were listening for it.
示例:
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放在脚本中的惯常做法
标签位于文档正文末尾,就在结束< / body>
标记之前,或者使用 async
或推迟
属性。这意味着可以在短暂的一段时间内点击页面上的任何按钮,但我们还没有将处理程序连接到它们上面。例如,如果存在临时网络故障,并且需要两秒钟而不是通常的~65ms来加载JavaScript文件,那么在您挂钩处理程序(正在监听它)之前,您的用户将单击按钮(触发事件)。
Well, the above is quite generic: Consider the usual practice of putting your JavaScript in a script
tag at the end of the document body, just before the closing </body>
tag, or using the async
or defer
attributes on it. That means there is a brief period of time when any buttons on the page can be clicked, but we haven't hooked up handlers on them yet. If there's a temporary network glitch, for instance, and it takes two seconds instead of the usual ~65ms to load your JavaScript file, your users would click the button (trigger the event) before you hooked your handler (were listening for it).
或者,这曾经是一个很好的例子,但据我所知,现代浏览器上不再出现 Kaiido说它仍然在WebKit浏览器上运行,虽然我无法在iOS Safari上实现:在文档中添加 img
并期望从这样的代码中获取load事件:
Alternately, this used to be a good example, but no longer happens on modern browsers as far as I can tell Kaiido says it still does on WebKit browsers, although I couldn't make it happen on iOS Safari: Adding an img
to a document and expecting to get the load event from code like this:
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线程上运行的事实。但是那里 是一个竞争条件,因为虽然我们的代码将遵循单个线程,但浏览器不是单线程的。所以这可能发生:
On the surface, it looks like there's no race condition there because of JavaScript's run-to-completion semantics and the fact that by default our JavaScript code runs on a single UI thread. But there is a race condition there, because while our code will follow a single thread, the browser is not single-threaded. So this can happen:
-
img.src =path / to / the / image.png;
。 - 浏览器的资源管理代码会查找图像。
- 资源管理在缓存中找到它而不是需要重新验证,因此将图像数据与元素关联并触发
加载
事件。 - 事件系统进入队列回调任何
加载
元素上的事件处理程序的任务,找不到任何任务,也不排队任何任务。 - 我们附上我们的处理程序并附加元素。
- 我们的代码运行完成。
- 我们永远不会得到
加载
或错误
事件回调。
img.src = "path/to/the/image.png";
.- The browser's resource management code goes looking for the image.
- Resource management finds it in cache and doesn't need to re-verify, so associates the image data with the element and triggers the
load
event. - The event system goes to queue tasks for callbacks to any
load
event handlers that are present on the element, doesn't find any, and doesn't queue any tasks. - We attach our handlers and append the element.
- Our code runs to completion.
- We never get either a
load
orerror
event callback.
相反,如果我们首先挂接 然后设置 src
:
In contrast, if we hook first and then set 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);
然后同样的情况如下:
- 我们附上我们的处理程序。
-
img.src =path / to / the / image.png;
。 - 浏览器的资源管理代码会查找图像。
- 资源管理在缓存中找到它并且不需要重新验证,因此将图像数据与元素相关联并触发
load
事件。 - 事件系统进入队列任务用于回调元素上存在的任何
加载
事件处理程序。它找到一个,所以当任务队列下一个空时,它会将一个任务排队。 - 我们附加元素。
- 我们的代码运行完成。
- 任务循环从队列中获取下一个任务,恰好是我们的
加载
回调。 - 任务循环调用我们的回调。
- We attach our handlers.
img.src = "path/to/the/image.png";
.- The browser's resource management code goes looking for the image.
- Resource management finds it in cache and doesn't need to re-verify, so associates the image data with the element and triggers the
load
event. - The event system goes to queue tasks for callbacks to any
load
event handlers that are present on the element. It finds one, so it queues a task to call it when the task queue is next empty. - We append the element.
- Our code runs to completion.
- The task loop picks up the next task from the queue, which happens to be our
load
callback. - The task loop calls our callback.
现在,碰巧这种行为非常令人厌烦现代浏览器不再这样做(尽管 Kaiido说它仍然在WebKit上,我无法确认)。虽然我仍然像它那样编码(第二个例子),因为可以,这是浏览器工作的有效方式。
Now, it happens that this behavior was sufficiently irksome that modern browsers don't do it anymore (although Kaiido says it still does on WebKit, I can't confirm that). Although I still code as though it does (the second example), because it could, it's a valid way for the browser to work.
这篇关于在我们开始收听事件之前发生的事件是什么意思?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!