Search code examples
electronipc

Electron IPC Main to Render Multiple listeners - listener argument must be a function


I am implementing the Electron's Pattern 3 which is Main to Render according to the following docs: https://www.electronjs.org/docs/latest/tutorial/ipc#pattern-3-main-to-renderer

I am getting the following error: enter image description here

My code:

main.js

autoUpdater.on('download-progress', (progress) => {
        if (progress && progress.percent) {
            updateWindow.webContents.send('sendProgress', Math.round(progress.percent));  // send update event to update.preload
        }
    })

    // Download finished
    autoUpdater.on('update-downloaded', () => {
        updateWindow.webContents.send('downloadComplete');
        setTimeout(() => {
            autoUpdater.quitAndInstall(true,true); // restarts the application and install the update after update has been downloaded
        }, 40000);   // TODO ======= change to 3000
    })

Here I am sending 2 messages. sendProgress and downloadComplete

preload.js

I declare the bridge in my preload

const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('bridge', {
        sendProgress: (progress) => {
            ipcRenderer.on('sendProgress', progress);
        },
        downloadComplete: () => {
            console.log('--IN download complete-- in preload.js');
            ipcRenderer.on('downloadComplete');
        }
    }
);

update.html

<script>
            window.bridge.sendProgress((event, progress) => {
                const element = document.getElementById('update-progress');
                if (element) {
                    element.innerText = progress;
                }
            })

            window.bridge.downloadComplete((event) => {
                const messageEl = document.getElementById('message');
                if (messageEl) {
                    console.log('altering innerText');
                    messageEl.innerText = 'Installing Update';
                }

                const progressEl = document.getElementById('progress');
                progressEl.style.display = 'none';

                const restartEl = document.getElementById('restart');
                restartEl.style.display = 'block';
            })


        </script>

The problem says my error lies at my 2nd listener of the update.html file, i.e. at

window.bridge.downloadComplete((event) => {

Also, when I just implemented the 1 listener then it worked, but as soon as I implemented the 2nd one it returned this error.


Solution

  • You need to add the callback variable to the arrow functions when declaring it in the preload script.

    Preload.js should look like this:

    // Import the necessary Electron modules
    const { contextBridge, ipcRenderer } = require('electron');
    
    contextBridge.exposeInMainWorld('bridge', {
            sendProgress: (callback) => ipcRenderer.on('sendProgress', callback),
            downloadComplete: (callback) => ipcRenderer.on('downloadComplete', callback)
        }
    );