Какова более правильная позиция для аргумента ошибки в обратном вызове JavaScript? - PullRequest
7 голосов
/ 17 мая 2011

Я пишу функцию JavaScript, которая принимает обратный вызов.Обратному вызову будет передан аргумент ошибки, если что-то пойдет не так.

Каковы лучшие / самые стандартные соглашения о вызовах?

  • Должен ли аргумент ошибки обратного вызова быть первым или последним?
  • Должен ли я передать 'errorMsg' строку или new Error('errorMsg') объект?

То есть, что более правильно - этот код:

foo = function(bar, callback) {
  ...
  if (error) {
    callback('troz not found');
  } else {
    callback(null, result);
  }
}

или этоткод:

foo = function(bar, callback) {
  ...
  if (error) {
    callback(null, 'troz not found');
  } else {
    callback(result);
  }
}

или это:

foo = function(bar, callback) {
  ...
  if (error) {
    callback(null, new Error('troz not found'));
  } else {
    callback(result);
  }
}

Если это уместно, мой код будет использоваться как в качестве модуля NodeJS, так и в качестве библиотеки JavaScript на основе браузера.

Ответы [ 4 ]

7 голосов
/ 17 мая 2011

Вы можете указать два обратных вызова, один для успеха и один для ошибки, и оба инкапсулированы в один аргумент "обратные вызовы". Вот как много библиотек Javascript обрабатывают ваше требование.

var fooFn = function(bar, callbacks) {
  callbacks = callbacks || {}; //make callbacks argument optional
  ...
  if (error) {
    if (callbacks.error) {
      callbacks.error('troz not found'); //pass the error message as a string
    }
  } else if (callbacks.success) {
    callbacks.success(result);
  }
}

Функции успеха и ошибок не являются обязательными. Чтобы указать оба, назовите это так:

fooFn("some bar", {
  success: function(result) {
    //success :-)
  },
  error: function(errorMsg) {
    //error :-(
  }
});

Вы также можете сделать это:

fooFn("some other bar");

Если хотите, вы можете расширить объект обратных вызовов для поддержки других сценариев, например, «завершить».

3 голосов
/ 17 мая 2011

В большинстве приложений node.js используется шаблон 'error-first' или шаблон EventEmitter. а именно:

// more common
if (error) {
  cb({make:'better'})
} else {
  cb(undefined, stronger)
}

или

// cleaner, perhaps, but more keystrokes
var ee = new EventEmitter
process.nextTick(function () {
  ...
  if (error) {
    ee.emit('error', {msg:'delicious'})
  } else {
    ee.emit('success', bacon)
  }
})
return ee
1 голос
/ 17 мая 2011

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

  1. Использование обратного вызова «success» и «error».
  2. Использование одного обратного вызова для обработки обоих «success» и «ошибки "случаи.
  3. Наличие механизма регистрации для стандартного обработчика" ошибки ", что делает необязательными обработчики ошибок для всех других вызовов, с использованием немедленных или резервных обратных вызовов ошибок в зависимости от ситуации.

В сочетании с:

  1. Без параметров для обратного вызова ошибки.
  2. Использование логического значения для обозначения успеха / неудачи.
  3. Использование строки для инкапсуляции характераошибка.
  4. Использование более сложного объекта "Результат" для инкапсуляции успеха / неудачи и результата.
  5. Использование некоторого сложного объекта для инкапсуляции подробной информации об ошибках.

На самом деле, это полностью зависит от вас.Это также зависит от того, что вы пытаетесь сделать.Например, если вы на самом деле не намерены что-либо делать с информацией об ошибках, то это может не стоить затрат на создание / передачу этой дополнительной информации.Но, возможно, у вас есть много подробной информации об ошибках, которую вы хотите передать пользователю или обратно вызывающей стороне API, и в этом случае это имеет большой смысл.

Выберите соглашение и придерживайтесь его.Кроме этого, это полностью зависит от вас.

0 голосов
/ 29 августа 2017

Кажется, у нас нет современного ответа:)

Теперь вы можете использовать Promise для него:

foo = function (bar) {
    return new Promise(function (resolve, reject) {
        ...
        if (error) {
            reject('troz not found');
        } else {
            resolve(result);
        }
    });
}

или проще, если действие синхронно:

foo = function (bar) {      
    ...
    if (error) {
        return Promise.reject('troz not found');
    } else {
        return Promise.resolve(result);
    }
}

и затем для обработки результата:

foo.then(callback)
   .catch(errorHandler);

, где

callback = function (result) {...}
errorHandler = function (errorMessage) {...}

, чтобы в случае ошибки не было выполнено обратный вызов (результат), в случае ошибкиerrorHandler ('troz not found') будет выполнен.

В качестве дополнительного преимущества - наличие обработчика результатов и обработчика ошибок отдельно.Хороший пример разделения интересов.

...