[英]Node .on method firing too many times
我有一个Electron应用程序,向用户显示目录列表。 当用户单击按钮时,我的界面脚本interface.js清除容器div并向main.js发送消息。 收到消息后,main.js将目录扫描成文件名数组,并将数组作为响应返回给interface.js。 Interface.js使用.on方法,该方法在收到响应时触发,并使用数组内容更新容器div。
这是我第一次使用Node的真正尝试,就接口行为而言,一切都运行得非常出色! 很棒,它只有几个小时,我已经爱上了Node!
但是,在调试/压力测试时,我将.on方法中返回的数组打印到控制台,并注意到一些奇怪的行为。 用户第一次单击该按钮时,.on方法将运行一次(通过一条消息验证到控制台)。 用户第二次单击时,该方法运行两次(通过两条消息验证到控制台); 它第三次运行三次,依此类推。
main.js中扫描目录的函数每次点击只运行一次,因此问题必须在inteface.js内。
我的main.js和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
}
} );
}
该代码改编自Electron网站上的教程。
为什么ipcRenderer.on
会多次运行? 每次点击按钮时它是否可能被绑定,因此可以像过去的点击一样运行多次? 我在事件监听器函数中放置了一个print语句,并在ipcRenderer
之前的showDialogue
函数内部,但是它们每次只打印一次,所以重复肯定只来自ipcRenderer.on
。
正如@planet_hunter所提到的,每次调用showDialogue()
都会设置一个监听器。 您需要删除侦听器或将侦听器移出调用函数。
但是,我发现更清晰的解决方案是使用.once
命令。 这类似.on
,但不是手动删除.on
监听器(你还没有),它会自行删除。
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
}
} );
}
您在每次单击按钮后订阅ipcRenderer.on
,这会导致多个订阅。 尝试在ipcRenderer.on
事件之外定义ipcRenderer.on
事件处理程序,它应该可以正常工作。
像这样的东西 -
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/' );
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.