Узел .on метод запускается слишком много раз - PullRequest
0 голосов
/ 31 августа 2018

У меня есть приложение 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 внутри функции прослушивателя событий и внутри функции showDialogue перед материалом ipcRenderer, но они оба печатаются только один раз за клик, поэтому повторы определенно исходят только из ipcRenderer.on.

Ответы [ 2 ]

0 голосов
/ 31 августа 2018

Как уже упоминалось @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
        }
    } );
}
0 голосов
/ 31 августа 2018

Вы подписываетесь на ipcRenderer.on после каждого нажатия кнопки, которое вызывает несколько подписок. Попробуйте определить обработчик события ipcRenderer.on вне события click, и он должен работать нормально.

Как то так -

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/' );
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...