【问题标题】:Bind variables to callback function将变量绑定到回调函数
【发布时间】:2013-07-17 22:15:19
【问题描述】:

我正在从我的请求处理程序中调用一些数据库函数。所有这些函数都为处理错误执行单独的“错误回调”。示例:

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);
    }
}

我有几个与此类似的请求处理程序,它们都调用不同的数据库函数。目前我已经将onError() 复制到它们每个的范围内,因为在处理错误时我需要reqres,但我认为可能有一种方法可以在没有重复的情况下实现相同的目标。

所以问题是,是否有可能以某种方式将reqres 绑定到onError(),这样我就不必将onError() 复制到每个请求处理程序中?

【问题讨论】:

    标签: javascript node.js


    【解决方案1】:

    绑定很简单!

    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.

    这是一个真正的基本演示

    // 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 中启用面向对象的样式。除非您使用这种风格,否则我认为没有理由关注上下文。

    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 是Partial Application

    在计算机科学中,部分应用(或部分函数应用)是指将多个参数固定到一个函数的过程,从而生成另一个更小数量的函数。

    在这里我们可以创建一个非常简单的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与绑定或部分应用有关,但不一样

    在数学和计算机科学中,柯里化是将接受多个参数(或参数元组)的函数的求值转换为对一系列函数进行求值的技术,每个函数都有一个参数。

    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

    【讨论】:

    • 链接很长,但它指向的内容,没有那么多! :)
    • 非常感谢您在尝试了几个小时后给出的清晰解释,我终于明白了 - 我在 ajax 成功回调中的回调函数遇到了这个问题,总是将它作为窗口对象而不是对象返回。 ` callbackFunc.bind($self)(cart);` 解决了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 2014-05-14
    • 1970-01-01
    相关资源
    最近更新 更多