Node .on method firing too many times

蓝咒 提交于 2021-01-27 07:29:21

问题


I have an Electron app that presents a directory listing to the user. When the user clicks a button my interface script, interface.js, clears the container div and sends a message to main.js. On receiving the message, main.js scans the directory into an array of filenames and returns the array to interface.js as a response. Interface.js uses a .on method that fires when the response is received and updates the container div with the contents of the array.

This is my first real attempt at using Node, and as far as interface behaviour went everything worked brilliantly! Wonderful, it's only been a few hours and I'm already loving Node!

However, while debugging/stress testing I printed the returned array within the .on method to the console and noticed some strange behaviour. The first time the user clicks the button, the .on method runs once (verified by one message to the console). The second time the user clicks, the method runs twice (verified by two messages to the console); the third time it runs three times and so on.

The function in main.js that scans the directory only runs once per click, so the issue must be within inteface.js.

My code for main.js and interface.js:

main.js:

const {app, BrowserWindow, ipcMain} = require('electron');
const fs = require('fs');

...

ipcMain.on( 'list-directory', ( event, directory ) => {
    var files = fs.readdirSync( directory );
    event.sender.send( 'list-directory-reply', files );
});

interface.js

var { ipcRenderer, remote } = require( 'electron' );  
var main = remote.require( "./main.js" );

...

button.addEventListener('click', function(){ showDialogue( this ); }, false );

...

showDialogue( select ) {
    // clear the dialogue
    // some other stuff
    ipcRenderer.send( 'list-directory', './files/documents/' );
    ipcRenderer.on( 'list-directory-reply', function( event, contents ) {
        console.log( contents );
        if ( contents.length > 0 ) {
            // add contents to the dialogue
        }
    } );
}

The code is adapted from a tutorial on the Electron website.

Why does ipcRenderer.on run multiple times? Is it possible that it's bound to something every time the button is clicked, and thus runs as many times as past clicks? I put a print statement inside the event listener function, and inside the showDialogue function before the ipcRenderer stuff, but they both only printed once per click so the repeats are definitely only coming from ipcRenderer.on.


回答1:


You are subscribing to ipcRenderer.on after every button click which is causing multiple subscriptions. Try to define the ipcRenderer.on event handler outside click event and it should work fine.

Something like this -

button.addEventListener('click', function(){ showDialogue( this ); }, false );


ipcRenderer.on( 'list-directory-reply', function( event, contents ) {
    // ipcRenderer event handler
});

showDialogue(select) {
    ipcRenderer.send( 'list-directory', './files/documents/' );
}



回答2:


As @planet_hunter mentioned, you are setting up a listener every time showDialogue() is called. You need to remove the listener or move the listener outside of the calling function.

However, I find a cleaner solution is to use the .once command. This behaves like .on, but instead of manually having to remove the .on listener (which you haven't done) it removes itself.

showDialogue( select ) {
    // clear the dialogue
    // some other stuff
    ipcRenderer.send( 'list-directory', './files/documents/' );
    ipcRenderer.once( 'list-directory-reply', function( event, contents ) {
        console.log( contents );
        if ( contents.length > 0 ) {
            // add contents to the dialogue
        }
    } );
}


来源:https://stackoverflow.com/questions/52111151/node-on-method-firing-too-many-times

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!