node.js 将变量绑定到回调函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17711211/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Bind variables to callback function
提问by rongved
I have a few functions in my controller which call some database functions. All of these database functions do "error callbacks", meaning that if a database error occur they do a separate callback which handles the error. Example:
我的控制器中有一些函数可以调用一些数据库函数。所有这些数据库函数都执行“错误回调”,这意味着如果发生数据库错误,它们会执行一个单独的回调来处理错误。例子:
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);
}
}
I have multiple functions similar to this, which are calling different database functions. The problem is that I at the moment have duplicated onError() into the scope of each of them, since I need the req and res variables when handling the error. I could of course pass res and req to the database function, and then pass them as arguments to the error callback, but I like think that there might be a better way.
我有多个与此类似的函数,它们调用不同的数据库函数。问题是我目前已将 onError() 复制到每个的范围内,因为在处理错误时我需要 req 和 res 变量。我当然可以将 res 和 req 传递给数据库函数,然后将它们作为参数传递给错误回调,但我认为可能有更好的方法。
So the question is: Is it possible to somehow bind res and req to a global onError callback function, in a way that I won't have to pass the variables as arguments to the db function?
所以问题是:是否有可能以某种方式将 res 和 req 绑定到全局 onError 回调函数,这样我就不必将变量作为参数传递给 db 函数?
I'm very new to node.js and javascript in general, so if there is a better way of handling errors, please let me know.
我对 node.js 和 javascript 很陌生,所以如果有更好的处理错误的方法,请告诉我。
回答by Thank you
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 thisof your function. Note you can only bind the context of functions defined with the functionkeyword; arrow functions have a lexical thisthat 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.
Context 允许您动态更改this函数的 。请注意,您只能绑定使用function关键字定义的函数的上下文;箭头函数有一个this无法操作的词法。这是为了完整性而显示的,但我建议不要使用这种程序。通常最好只使用另一个函数参数而不是依赖动态函数上下文this. 支持这样的上下文切换是为了在 JavaScript 中启用面向对象的风格。除非你使用这种风格,否则我认为没有理由关注上下文。
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
类似于binding 是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 partialhelper procedure which helps us accomplish this
在这里,我们可以制作一个非常简单的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 ]
Currying
咖喱
Curryingis 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

