我的控制器中有一些函数可以调用一些数据库函数。所有这些数据库函数都执行“错误回调”,这意味着如果发生数据库错误,它们将执行一个单独的回调来处理该错误。例:
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还是很陌生,所以如果有更好的错误处理方法,请告诉我。
绑定很简单!
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 = 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
上下文?
上下文允许您动态更改this功能。注意,您只能绑定用function关键字定义的函数的上下文;箭头函数具有this无法操纵的词汇。为了完整起见,显示了此内容,但我建议不要使用此类程序。通常最好只使用另一个函数参数,而不要依赖动态函数上下文this。支持这样的上下文切换是为了在JavaScript中启用面向对象的样式。除非您使用这种样式,否则我认为没有理由注意上下文。
this
function
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>
部分申请
类似于binding is Partial Application
bind
在计算机科学中,部分应用程序(或部分函数应用程序)指的是将多个参数固定到一个函数,从而产生另一个arity较小的函数的过程。
在这里,我们可以制作一个非常简单的partial帮助程序,以帮助我们完成此任务
partial
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 ]
咖喱
固化与绑定或部分应用有关,但不相同
在数学和计算机科学中,柯里化是一种将接受多个自变量(或自变量元组)的函数的评估转换为评估每个具有一个自变量的函数序列的技术。
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