带响应的自定义事件,这可能吗?

cas*_*raf 5 javascript events

我正在尝试将 CustomEvent 合并到我的工作流程中。但我需要此事件以两种方式进行通信:脚本将事件发送到文档,并且它应该响应相同的发起者。

我尝试过以下方法:

ev = new CustomEvent('StorageRequest', {
  detail: {
    space: theSpace,
    method: theMethod,
    arguments: args
  }
})
document.dispatchEvent(ev)
Run Code Online (Sandbox Code Playgroud)

我的听众看起来像这样:

document.addEventListener('StorageRequest', (e) => {
  console.debug('Sending StorageRequest', e)
  // do something, then answer back with response
})
Run Code Online (Sandbox Code Playgroud)

有什么办法可以达到这个目的呢?

我尝试过使用 Promise 并使用解析/拒绝发送响应,但传递函数似乎会破坏detail事件,如果我尝试这样做,结果将为空:

return new Promise((resolve, reject) => {
  ev = new CustomEvent('StorageRequest', {
    detail: {
      space: theSpace,
      method: theMethod,
      arguments: args,
      resolve, reject
    }
  })
  document.dispatchEvent(ev)
})
Run Code Online (Sandbox Code Playgroud)

注意: 我想避免“一般”将响应发送回文档。我更喜欢请求和响应是完全有意的,并在代码中正确处理
,我没有附加任何元素,所以使用来自的元素e.target不是一个选项(除非我可以用它做其他事情)

Jim*_*Jim 2

您无法在 DOM 事件中“响应” - 它们只是向上传播 DOM 树,直到到达顶层。

承诺可能有效,设置正确,但您只能回复一次。一旦承诺被解决/拒绝,您就无法再次解决或拒绝它,它将忽略后续的解决/拒绝调用。

作为替代方案,您可以设置 2 个单独的事件并响应第一个事件,这应该实现您尝试执行的操作:

sReqEvent = new CustomEvent('StorageRequest', {
    detail: {
    space: theSpace,
    method: theMethod,
    arguments: args
});

console.debug('Sending StorageRequest');
document.dispatchEvent(sReqEvent);
Run Code Online (Sandbox Code Playgroud)

听众:

document.addEventListener('StorageRequest', (e) => {
    // do something, then answer back with response
    var sRespEvent = new CustomEvent('StorageResponse', e.data);
    console.debug('Sending StorageResponse', e.data);
    document.dispatchEvent(sRespEvent);
});

document.addEventListener('StorageResponse', (e) => {
    // This is my response
});
Run Code Online (Sandbox Code Playgroud)

当然这是不必要的,您可以只使用从 StorageRequest 侦听器中调用的“StorageResponse”函数...


另一种替代方法是使用window.postMessage,但这更多地涉及到单独的来回请求的设置,并且 IE9 将仅支持传递字符串(如果您想发送字符串以外的任何内容,则需要在 IE9 中对包进行 JSON 编码/解码 -有效,但如果您在所有浏览器中作为全局解决方法执行此操作,速度会更慢)。