const Disposable = require('event-kit').Disposable
let ipcRenderer = null
let ipcMain = null
let BrowserWindow = null

exports.on = function (emitter, eventName, callback) {
  emitter.on(eventName, callback)
  return new Disposable(() => emitter.removeListener(eventName, callback))
}

exports.call = function (channel, ...args) {
  if (!ipcRenderer) {
    ipcRenderer = require('electron').ipcRenderer
    ipcRenderer.setMaxListeners(20)
  }

  const responseChannel = getResponseChannel(channel)

  return new Promise(resolve => {
    ipcRenderer.on(responseChannel, (event, result) => {
      ipcRenderer.removeAllListeners(responseChannel)
      resolve(result)
    })

    ipcRenderer.send(channel, ...args)
  })
}

exports.respondTo = function (channel, callback) {
  if (!ipcMain) {
    const electron = require('electron')
    ipcMain = electron.ipcMain
    BrowserWindow = electron.BrowserWindow
  }

  const responseChannel = getResponseChannel(channel)

  return exports.on(ipcMain, channel, async (event, ...args) => {
    const browserWindow = BrowserWindow.fromWebContents(event.sender)
    const result = await callback(browserWindow, ...args)
    event.sender.send(responseChannel, result)
  })
}

function getResponseChannel (channel) {
  return 'ipc-helpers-' + channel + '-response'
}

@@ -112,16 +112,47 @@
 = null%0A%0A
+let nextResponseChannelId = 0%0A%0A
 exports.
@@ -498,35 +498,57 @@
 l = 
-getResponseChannel(channel)
+%60ipc-helpers-response-$%7BnextResponseChannelId++%7D%60
 %0A%0A  
@@ -741,32 +741,49 @@
 er.send(channel,
+ responseChannel,
  ...args)%0A  %7D)%0A%7D
@@ -977,63 +977,8 @@
  %7D%0A%0A
-  const responseChannel = getResponseChannel(channel)%0A%0A
   re
@@ -1024,16 +1024,33 @@
  (event,
+ responseChannel,
  ...args
@@ -1235,102 +1235,11 @@
 lt)%0A
+
   %7D)%0A%7D%0A
-%0Afunction getResponseChannel (channel) %7B%0A  return 'ipc-helpers-' + channel + '-response'%0A%7D%0A

Handle concurrent calls to the same channel in ipc helpers