在我们开始收听事件之前发生的事件是什么意思? [英] What is meant by saying that events happened before we started listening to them?

查看:63
本文介绍了在我们开始收听事件之前发生的事件是什么意思?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在阅读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:


  1. img.src =path / to / the / image.png;

  2. 浏览器的资源管理代码会查找图像。

  3. 资源管理在缓存中找到它而不是需要重新验证,因此将图像数据与元素关联并触发加载事件。

  4. 事件系统进入队列回调任何加载元素上的事件处理程序的任务,找不到任何任务,也不排队任何任务。

  5. 我们附上我们的处理程序并附加元素。

  6. 我们的代码运行完成。

  7. 我们永远不会得到加载错误事件回调。

  1. img.src = "path/to/the/image.png";.
  2. The browser's resource management code goes looking for the image.
  3. 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.
  4. 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.
  5. We attach our handlers and append the element.
  6. Our code runs to completion.
  7. We never get either a load or error 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);

然后同样的情况如下:


  1. 我们附上我们的处理程序。

  2. img.src =path / to / the / image.png;

  3. 浏览器的资源管理代码会查找图像。

  4. 资源管理在缓存中找到它并且不需要重新验证,因此将图像数据与元素相关联并触发 load 事件。

  5. 事件系统进入队列任务用于回调元素上存在的任何加载事件处理程序。它找到一个,所以当任务队列下一个空时,它会将一个任务排队。

  6. 我们附加元素。

  7. 我们的代码运行完成。

  8. 任务循环从队列中获取下一个任务,恰好是我们的加载回调。

  9. 任务循环调用我们的回调。

  1. We attach our handlers.
  2. img.src = "path/to/the/image.png";.
  3. The browser's resource management code goes looking for the image.
  4. 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.
  5. 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.
  6. We append the element.
  7. Our code runs to completion.
  8. The task loop picks up the next task from the queue, which happens to be our load callback.
  9. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆