Last active
May 26, 2024 09:19
-
-
Save benoitlahoz/de6c41f5024d111ce37034efe1bf8443 to your computer and use it in GitHub Desktop.
IPC communication in Electron with client-side callback.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Renderer. | |
/** | |
* Describes the function used to call `invoke` on ipcRenderer. | |
*/ | |
type InvokeFn = (channel: string, ...args: any[]) => Promise<any>; | |
/** | |
* The `invoke` function returned by the `exposeInMainWorld` of the preload script | |
* or by `ipcRenderer` itself. | |
*/ | |
let apiInvoke: InvokeFn | undefined; | |
/** | |
* Register the function to `invoke` the main process. | |
* | |
* @param { InvokeFn } invoke The function that will be called to trigger `handle` in the main process. | |
*/ | |
export const register = (invoke: InvokeFn): void => { | |
if (apiInvoke) { | |
console.warn("Already registered API's `invoke` function is being overwritten."); | |
} | |
apiInvoke = invoke; | |
}; | |
/** | |
* Invoke a handler of the main process, and trigger the provided callback on response. | |
* | |
* @param { string } channel The channel to invoke. | |
* @param { ...any[] } args Any data to send to the main process handler, and a callback at the end. | |
* The callback will be called when the result is returned by the main process. | |
*/ | |
export const emit = async (channel: string, ...args: any[]): Promise<void> => { | |
if (!apiInvoke) { | |
throw new Error(`API's 'invoke' function was not registered.`); | |
} | |
if (args.length > 0) { | |
// Get the last arguments that may be a callback or NoOp. | |
const maybeCallback = typeof args[args.length - 1] === 'function' ? args[args.length - 1] : (..._: any[]) => {}; | |
// Get the data to pass to the IPC. | |
const data = [...args]; | |
data.splice(data.length - 1, 1); | |
const res = await apiInvoke(channel, ...data); | |
maybeCallback(res); | |
return; | |
} | |
// Invoke without data. | |
await apiInvoke(channel); | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Main process. | |
import { ipcMain } from 'electron'; | |
ipcMain.handle('ping', async (event: IpcMainInvokeEvent, data: string) => { | |
return `pong: ${data}`; | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { ipcRenderer } from 'electron'; | |
import { register, emit } from 'ipc-emit'; | |
// Register the ipcRenderer.invoke function to be used in 'emit'. | |
register(ipcRendererr.invoke); | |
(async () => { | |
await emit('ping', 'foo', (res: string) => { | |
console.log(res); // pong: foo | |
} | |
})(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { register, emit } from 'ipc-emit'; | |
const invoke = window['MyAPI'].invoke; | |
// Register the preload script API 'invoke' function to be used in 'emit'. | |
register(invoke); | |
(async () => { | |
await emit('ping', 'foo', (res: string) => { | |
console.log(res); // pong: foo | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment