Идиоматическая обработка ошибок узла

Итак, я делаю учебник по nodejs, и он просит меня использовать модули для фильтрации всех файлов в каталоге. И я должен использовать идиоматический подход для обработки ошибок. Ниже мои modules.js и мой основной program.js, однако программа сказала, что

Your additional module file [module.js] does not appear to pass back an
error received from fs.readdir(). Use the following idiomatic Node.js
pattern inside your callback to fs.readdir():
if (err) return
callback(err)

но я обработал ошибку в первой строке, используя if (err)return callback(err);

Может ли кто-нибудь указать, что я делаю неправильно или какие передовые методы я не придерживаюсь? Спасибо

module.exports = function filterList(dirName, extName, callback) {

fs.readdir(dirName, function callback(err, list) {

    if (err)
        return callback(err);
    for (var i = 0; i < list.length; i++) {
        if (path.extname(list[i]) == '.' + extName) {
            callback(null, list[i]);
        }
    };
});
}

мой program.js выглядит следующим образом

var myMod = require('./module');
function printOut(err, result) {
    if (err) {
        console.log(err);
    };
    console.log(result);
}

myMod(process.argv[2], process.argv[3], printOut);

person UWGOOSE    schedule 28.02.2018    source источник


Ответы (2)


У вас есть две функции с именем callback, которые вызывают неожиданное поведение.

Ваша основная экспортируемая функция принимает имя аргумента callback. Затем внутри вы определяете другую функцию с именем callback:

function filterList(dirName, extName, callback){ // <-- callback as arg
    fs.readdir(dirName, function callback(err, list) { // <-- callback defined again
        if (err)
          return callback(err);  // <-- which function is this calling?
  /* etc. */
}

Когда вы, наконец, return callback(err), вы вызываете не ту функцию. Вы хотите вызвать первый - тот, который передан в filterList(), но второй находится в области видимости.

Вместо этого вы можете передать анонимную функцию fs.readdir, поскольку вам никогда не нужно ее вызывать:

 fs.readdir(dirName, function(err, list) {
    if (err)
      return callback(err);  // <-- now there's only one call back

Теперь ясно, что вы вызываете правильный обратный вызов, и это более идиоматично.

person Mark    schedule 28.02.2018

Вы скрываете свой callback, называя функцию так же, как аргумент. Попробуй это:

module.exports = function filterList(dirName, extName, callback) {
  fs.readdir(dirName, function cb(err, list) {
    if (err) return callback(err);
    for (var i = 0; i < list.length; i++) {
      if (path.extname(list[i]) == '.' + extName) {
        callback(null, list[i]);
      }
    };
  });
}

Обратите внимание, что переименование второго параметра в fs.readdir теперь называется cb, на самом деле вам не нужно его называть, но это помогает для трассировки стека и ведения журнала.

Еще одна вещь: у вас может возникнуть проблема с вызовом callback внутри цикла. Есть способы вырваться из этого состояния, а также способы избежать его зацикливания.

person Alexander Kahoun    schedule 28.02.2018