Привязать переменные к функции обратного вызова

23

У меня есть несколько функций в контроллере, которые вызывают некоторые функции базы данных. Все эти функции базы данных выполняют "обратные вызовы", что означает, что при возникновении ошибки базы данных они выполняют отдельный обратный вызов, который обрабатывает ошибку. Пример:

exports.referralComplete = function(req, res){
    /*getting id etc.*/
    db.startDatabaseConnection(function() {
        db.flagReferralAsDone(id, function(success) {
            db.endDatabaseConnection();
            /*doing stuff on success*/
        }, onError);
    }, onError);

    function onError(err, description) {
        logger.error(description + ": " + err);
        user.pageNotFound(req, res);
    }
}

У меня есть несколько функций, подобных этому, которые вызывают разные функции базы данных. Проблема в том, что я на данный момент дублировал onError() в область каждого из них, так как мне нужны переменные req и res при обработке ошибки. Я мог бы, конечно, передать res и req функции базы данных, а затем передать их в качестве аргументов для обратного вызова ошибки, но мне нравится думать, что может быть лучший способ.

Итак, возникает вопрос: возможно ли каким-либо образом связывать res и req с глобальной функцией обратного вызова onError таким образом, что мне не придется передавать переменные в качестве аргументов функции db?

Я очень новичок в node.js и javascript в целом, поэтому, если есть лучший способ обработки ошибок, сообщите мне.

Теги:

1 ответ

43
Лучший ответ

Связывание простое!

db.startDatabaseConnection(function(){
  // whatever
}, onError.bind(this, var1, var2));

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

Вот настоящая базовая демонстрация

// a function
var something = function (a, b, c) {
  console.log(a, b, c);
};

// a binding of something with 3 defined args
var b = something.bind(null, 1, 2, 3);

// call b
b();
//=> 1 2 3

За кулисами это в основном то, что происходит

// ES6
const myBind = (f, context, ...x) =>
  (...y) => f.call(context, ...x, ...y);

// ES5
var myBind = function(fn, context) {
  var x = [].slice.call(arguments, 2);
  return function() {
    var y = [].slice.call(arguments, 0); 
    return fn.apply(context, x.concat(y));
  };
};

var b = myBind(console.log, console, 1, 2, 3);

b();
// => 1 2 3

b(4,5,6)
// => 1 2 3 4 5 6 

Частичное приложение

Аналогично bind ing Частичное приложение

В информатике частичное приложение (или приложение частичной функции) относится к процессу фиксации ряда аргументов функции, создавая другую функцию меньшей arity.

Здесь мы могли бы сделать очень простую partial вспомогательную процедуру, которая поможет нам выполнить этот

const partial = (f, ...x) => (...y) => f(...x, ...y)

const foo = (...args) => console.log(args)

partial (foo, 1, 2, 3) (4, 5, 6)
// [ 1, 2, 3, 4, 5, 6 ]

Карринг

Currying связано с, но не совпадает с привязкой или частичным приложением

В математике и информатике каррирование - это метод перевода оценки функции, которая принимает несколько аргументов (или кортеж аргументов) в оценку последовательности функций, каждая из которых имеет один аргумент.

const curry = f => {
  let aux = (n, k) =>
    n === 0 ? k ([]) : x => aux (n - 1, xs => k ([x, ...xs]))
  return aux (f.length, xs => f (...xs))
}

const foo = (a, b, c) => console.log(a, b, c)

curry (foo) (1) (2) (3)
// 1 2 3
  • 2
    Ссылка длинная, но содержание, на которое она указывает, не так уж много! :)
  • 0
    Большое спасибо за ясное объяснение после долгих часов, которые я наконец получил - у меня была эта проблема с функцией обратного вызова в обратном вызове ajax success, всегда возвращая это как объект окна, а не объект. `callbackFunc.bind ($ self) (cart);` решил это

Ещё вопросы

Сообщество Overcoder
Наверх
Меню