I'm calling some database functions from my request handlers. All of these functions do separate "error callbacks" for handling errors. Example:
function referralComplete(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); } }
I have several request handlers similar to this all calling different database functions. At the moment I have duplicated onError()
into the scope of each of them since I need req
and res
when handling the error, but I like think that there might be a way to achieve the same without the duplication.
So the question is, would it be possible to somehow bind req
and res
to onError()
so that I won't have to duplicate onError()
into each request handler?
Explicitly set this of the callback - part 1bind [docs], which returns a new function with this bound to a value. The function has exactly the same behavior as the one you called . bind on, only that this was set by you. No matter how or when that function is called, this will always refer to the passed value.
Yes. The print( ) function takes another function as a parameter and calls it inside. This is valid in JavaScript and we call it a “callback”. So a function that is passed to another function as a parameter is a callback function.
Passing the event object of react as the second argument. If you want to pass a parameter to the click event handler you need to make use of the arrow function or bind the function. If you pass the argument directly the onClick function would be called automatically even before pressing the button.
Binding is simple!
db.startDatabaseConnection(function(){ // whatever }, onError.bind(this, var1, var2));
You can learn more about binding by clicking this awesome link, even though the link is sort of long.
Here's a real basic demo
// 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
Behind the scenes, this is basically what's happening
// ES6 const myBind = (f, context, ...x) => (...y) => f.call(context, ...x, ...y); // ES5 var myBind = function(fn, context) { var x = Array.prototype.slice.call(arguments, 2); return function() { var y = Array.prototype.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
Context?
Context allows you to dynamically change the this
of your function. Note you can only bind the context of functions defined with the function
keyword; arrow functions have a lexical this
that cannot be manipulated. This is shown for sake of completeness, but I do advise against this kind of program. It's usually better to just use another function parameter instead of relying on dynamic function context, this
. Supporting context switching like this is to enable object-oriented style in JavaScript. Unless you are using this style, I see no reason to pay attention to context.
const getCanvas = (id) => document.getElementById(id).getContext('2d') const draw = function (canvas, x = 0, y = 0) { canvas.beginPath() canvas.strokeStyle = this.color // `this` refers to context! canvas.rect(x, y, this.width, this.height) // `this` refers to context! canvas.stroke() } // create two contexts const contextA = { color: 'blue', width: 10, height: 10 } const contextB = { color: 'green', width: 10, height: 20 } // bind the draw function to each context and the canvas const drawA = draw.bind(contextA, getCanvas('main')) const drawB = draw.bind(contextB, getCanvas('main')) // call the bound drawing functions normally // draw three blue squares drawA(0, 0) drawA(20, 0) drawA(40, 0) // and one green rect drawB(80, 0)
<canvas id="main"></canvas>
Partial application
Similar to bind
ing is Partial Application
In computer science, partial application (or partial function application) refers to the process of fixing a number of arguments to a function, producing another function of smaller arity.
Here we could make a very simple partial
helper procedure which helps us accomplish this
const identity = x => x const partial = (f = identity, ...x) => (...y) => f (...x, ...y) const foo = (...all) => console.log ('array of', all) partial (foo, 1, 2, 3) (4, 5, 6) // 'array of', [ 1, 2, 3, 4, 5, 6 ]
Currying
Currying is related to, but not the same as, binding or partial application
In mathematics and computer science, currying is the technique of translating the evaluation of a function that takes multiple arguments (or a tuple of arguments) into evaluating a sequence of functions, each with a single argument.
const identity = x => x const curry = (f = identity, arity = f.length) => x => { const next = (xs = []) => xs.length >= arity ? f (...xs) : x => next ([ ...xs, x ]) return next ([ x ]) } const foo = (a, b, c) => console.log ('a', a, 'b', b, 'c', c) curry (foo) (1) (2) (3) // 'a' 1 'b' 2 'c' 3 curry (foo) ('choo') ('bye') () // 'a' 'choo' 'b' 'bye' 'c' undefined
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With