Node .on 方法触发太多次

2022-01-10 00:00:00 node.js electron javascript

我有一个 Electron 应用程序,它向用户显示目录列表.当用户单击一个按钮时,我的界面脚本 interface.js 会清除容器 div 并向 main.js 发送一条消息.收到消息后,main.js 将目录扫描成一个文件名数组,并将该数组作为响应返回给 interface.js.Interface.js 使用 .on 方法,在收到响应时触发并使用数组的内容更新容器 div.

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.

这是我第一次真正尝试使用 Node,就界面行为而言,一切都非常出色!太棒了,才几个小时,我已经爱上了 Node!

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!

但是,在调试/压力测试时,我将 .on 方法中返回的数组打印到控制台,并注意到一些奇怪的行为.用户第一次单击按钮时,.on 方法运行一次(通过向控制台发送一条消息进行验证).用户第二次点击,该方法运行两次(通过向控制台发送两条消息验证);第三次运行三次,以此类推.

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.

main.js中扫描目录的函数每次点击只运行一次,所以问题一定在interface.js中.

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

我的 main.js 和 interface.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

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
        }
    } );
}

代码改编自 Electron 网站上的教程.

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

为什么 ipcRenderer.on 会运行多次?是否有可能每次单击按钮时都绑定到某些东西,因此运行次数与过去的单击次数一样多?我在事件侦听器函数内和 showDialogue 函数内放置了一个打印语句,在 ipcRenderer 东西之前,但它们每次点击都只打印一次,所以重复肯定只会出现来自 ipcRenderer.on.

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.

推荐答案

您在每次点击按钮后订阅 ipcRenderer.on 导致多次订阅.尝试在 click 事件之外定义 ipcRenderer.on 事件处理程序,它应该可以正常工作.

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.

类似的东西 -

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/' );
}

相关文章