Я создаю простой SFTP-клиент с Electron, и я пытаюсь загрузить или загрузить несколько файлов одновременно, используя модуль ssh2 и SFTPStream в этом модуле. Я пробовал много различных структур методов, некоторые из которых включают использование es6-обещания-пула. Каждая попытка сделать результаты приводит к тому, что один файл из массива файлов передается должным образом, а затем
MaxListenersExceededWarning: Обнаружена возможная утечка памяти в EventEmitter. 11 слушателей sftp_message добавлены в [EventEmitter]. Используйте emitter.setMaxListeners () для увеличения лимита
сообщение отображается в консоли, а остальные файлы не передаются. Я не уверен, как изменить структуру моего метода, чтобы предотвратить это. Я использую ipcRenderer, чтобы сказать ipcMain выполнить методы, которые я покажу здесь (вот моя структура для загрузки файлов, например).
let counter = 0;
// Upload local file to server
ipcMain.on('upload_local_files', (event, args) => { // args[0] is connection settings, args[1] is array of file paths
let conn = new Client();
conn.on('ready', () => {
let pool = new PromisePool(uploadFileProducer(conn, args[1]), 10);
pool.start().then(() => {
conn.end();
counter = 0;
let tempArgs = [];
tempArgs.push(curLocalDir);
tempArgs.push(curRemoteDir);
event.sender.send('local_upload_complete', tempArgs);
});
}).connect(args[0]);
});
// Producer used in promise pool to upload files
function uploadFileProducer(conn, files){
if(counter < 100 && counter < files.length){
counter++;
return(uploadFile(conn, files[counter - 1]));
}else{
return null;
}
}
// Function used to upload files in promise pool
function uploadFile(conn, file){
return new Promise((resolve, reject) => {
conn.sftp((error, sftp) => {
return sftp.fastPut(file, curRemoteDir + file.substring(file.lastIndexOf('/') + 1), {}, (error) => {
resolve(file);
});
});
});
}
По общему признанию, использование пулов обещаний является новым для меня, и я не уверен, собираюсь ли я использовать их должным образом. В другом посте на эту тему использовались пулы обещаний, чтобы предотвратить возникновение проблемы, но в этом примере не было приложения Electron (я не знаю, уместно ли это). Я ценю любую помощь, которую я могу получить!
1 ответ
Проблема не в Warning
, это просто предупреждение, и обычно в вашем текущем случае использования. Проблема с загрузками заключается в неправильном использовании PromisePool
.
Я предполагаю, что вы используете ES6 - обещание бассейн
Вы должны передать функцию производителя обещания в конструктор, но вместо этого вы вызываете функцию и передаете обещание, поэтому загружаются только отдельные файлы.
Вы должны передать производителя, не вызывая его, или сделать производителя, который возвращает функцию, или использовать генератор.
Конструктор PromisePool принимает функцию Promise в качестве первого аргумента.
function *uploadFileProducer(conn, files) {
for(const file of files)
yield uploadFile(conn, file);
}
Теперь вы можете позвонить:
let pool = new PromisePool(uploadFileProducer(conn, args[1]), 10)
И PromisePool
будет правильно выполнять итерацию, возвращаемую функцией генератора, и соответственно обрабатывать параллелизм.
Вы также можете создать функцию, которая будет возвращать Promise
каждый вызов.
function uploadFileProducer(conn, files) {
files = files.slice(); // don't want to mutate the original
return () => uploadFile(conn, files.shift())
}
Что касается предупреждения, это нормально, если вы загружаете несколько вещей одновременно, если это так, вы можете увеличить лимит, используя:
emitter.setMaxListeners(n)
Похожие вопросы
Новые вопросы
javascript
По вопросам программирования на ECMAScript (JavaScript / JS) и его различных диалектах / реализациях (кроме ActionScript). Включите все соответствующие теги в свой вопрос; например, [node.js], [jquery], [json] и т. д.