Могу ли я сделать FTP-файл node.js синхронным?

У меня есть небольшой сценарий FTP, который в основном передает все дерево каталогов (путем его fs.readdir) на FTP-сервер по одному файлу за раз (мне нужно провести некоторый анализ каждого файла, так как он загружен, следовательно, поведение по одному).

Тем не менее, бит, который делает один файл (есть еще один бит для каталогов, которые используют c.mkdir скорее, чем c.put) выглядит так:

console.log('Transferring [' + ival + ']');
var c = new Ftp();
c.on('ready', function() {
    c.put(ival, ival, function(err) {
        console.log(err);
    });
    c.end();
});

Как вы можете видеть, он использует очень простой метод входа в систему, при котором сбои просто отправляются на консоль.

К сожалению, поскольку FTP выполняются асинхронно, ошибки доставляются на консоль в последовательности, совершенно не связанной с выводом имени файла.

Есть ли способ заставить FTP выполняться синхронно, чтобы ошибки сразу же следовали за именем файла? В принципе, я хочу всю последовательность из начальной console.log в финал }); должно быть сделано, прежде чем перейти к следующему файлу.

3 ответа

Решение

Даже если есть, это не рекомендуется. Как правило, вы не хотите блокировать цикл обработки событий с такой длинной синхронной операцией.

Что может быть более полезным, так это использование рекурсии или обещаний для обеспечения последовательности событий.

Пример:

let ivals = [/* lots of ivals here */];
function putItems(ivals) {
    let ival = ivals[0];
    console.log('Transferring [' + ival + ']');
    var c = new Ftp();
    c.on('ready', function() {
        c.put(ival, ival, function(err) {
            console.log(err);
            c.end();
            // Don't continue if we're out of items.
            if (ivals.length === 1) { return; } 
            putItems(ivals.slice(1)); // Call again with the rest of the items.
        });
    });
}

putItems(ivals);

Вероятно, это можно сделать более разумно, используя вложенную функцию и один FTP-контекст. Но вы поняли.

Не делая вещи синхронными, вы можете решить проблему регистрации ошибок, просто записав имя с ошибкой. Вы можете просто обернуть это в закрытие, чтобы вы могли отслеживать ival это идет с конкретной ошибкой:

(function(ival) {
    console.log('Transferring [' + ival + ']');
    var c = new Ftp();
    c.on('ready', function() {
        c.put(ival, ival, function(err) {
            console.log('[' + ival + ']', err);
        });
        c.end();
    });
})(ival);

Почему вы просто не помещаете ошибки в массив, и когда все загрузки будут завершены, у вас будет этот массив со всеми этими ошибками по порядку?

Я сделаю что-то вроде этого:

var errArray = [];
console.log('Transferring [' + ival + ']');
var c = new Ftp();
c.on('ready', function() {
  c.put(ival, ival, function(err) {
    errArray.push( err );
  });
  c.end();
});
c.on('end', function() {
  errArray.forEach( function( err ){
    console.log( err );
  })
});
Другие вопросы по тегам