是否有任何立即发生的DOM /浏览器API事件或回调(中断当前流程)

时间:2018-07-02 09:19:02

标签: javascript html5

大多数JavaScript / HTML / DOM /浏览器回调和事件不是立即发生的,也不是不可重入的(不确定此处是否正确)。我的意思是,即使有事件发生,它也被添加到浏览器的队列中,直到当前事件退出后才进行处理。

例如,如果我尝试加载图像

 const img = new Image();
 img.onload = function() {
   console.log("image loaded");
 }
 img.src = 'https://i.imgur.com/ZKMnXce.png';
 for (let i = 0; i < 100000; ++i) {
   console.log(i);
 }

假定浏览器没有超时,则可以保证在传递for事件之前运行以上onload循环。

另一个示例可能是postMessage

 window.onmessage = function() {
    console.log('got message');
 }
 window.postMessage({}, '*');
 for (let i = 0; i < 100000; ++i) {
   console.log(i);
 }
 

同样,循环将在消息事件到达之前结束。

这2个都是事件,但是当然有像setTimeoutrequestAnimationFrame这样的函数需要回调。

requestAnimationFrame(function() {
  console.log('requestAnimationFrame');
});
setTimeout(function() {
  console.log('setTimeout');
}, 0);
for (let i = 0; i < 100000; ++i) {
  console.log(i);
}

同样,循环将在调用rAF或setTimeout回调之前完成。

现在当然可以手动编写采用立即调用的回调的API。实际上,AFAICT是一个常见错误,被认为是一种反模式。例子

 /*
  * @param {*} params The params
  * @param {function(error, result)} callback where first param is error, null on success
  */
 function doSomethingAsyncThenCallback(params, callback) {
    if (params are bad) {
      callback("bad params");
      return;
    }
    dSomethingAsync then callback(null, result)
 }

被认为是错误模式的AFAIK,因为用户可能不希望回调函数在当前事件退出之前到达。推荐的写类似方法的方法是

 /*
  * @param {*} params The params
  * @param {function(error, result)} callback where first param is error
  */
 function someSomethingAsyncThenCallback(params, callback) {
    if (params are bad) {
      setTimeout(() => { callback("bad params"); }, 0);
      return;
    }
    do something async then callback(null, result)
 }

这样,无论用户使用什么代码,回调都将在当前事件结束后到达。

所以,我的问题是:是否有可能会出现回调/事件的浏览器API(如内置在浏览器中的API,例如XHR,canvas 2d,WebGL,WebAudio,加密,游戏手柄,websocket,webrtc,localstorage等)当前事件即将结束之前吗?

我知道JavaScript不能被打断。但是,就像上面执行不佳的JS api一样,成功后将等待当前事件退出,但失败后将立即调用回调,它们的本机浏览器API是否都具有这种行为?

0 个答案:

没有答案