Monday, May 13, 2024
 Popular · Latest · Hot · Upcoming
162
rated 0 times [  164] [ 2]  / answers: 1 / hits: 75041  / 11 Years ago, wed, july 17, 2013, 12:00:00

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?


More From » node.js

 Answers
15

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 binding 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




[#76920] Wednesday, July 17, 2013, 11 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
benitoh

Total Points: 150
Total Questions: 113
Total Answers: 104

Location: India
Member since Wed, Aug 26, 2020
4 Years ago
benitoh questions
Sun, Mar 21, 21, 00:00, 3 Years ago
Mon, May 13, 19, 00:00, 5 Years ago
;