【问题标题】:Calling a parent function inside a closure在闭包内调用父函数
【发布时间】:2016-09-04 18:35:48
【问题描述】:

我在尝试在异步soap请求中调用对象函数时遇到了非常非常困难的事情。基本上可以归结为:

function Thing(request, response) {

    this.foo = function() {
        console.log("this is foo");
    }

    this.doThing = function() {
        // Get SOAP args
        args = { foo: this.request.cookies.foo };
        // From the SOAP npm package library
        soap.createClient(function(err, client) {
            client.doSomething(args, function(err, result) {
                // Somehow call foo(); <--- CAN'T FIND A WAY TO DO THIS
            });
        });
    }
}
// Make it so I can access this.request and this.response somehow
Thing.prototype = Object.create(AbstractThing); 

我已经尝试了很多东西,但我相信这从根本上归结为我不能在任何异步肥皂函数中调用 this.foo()。虽然我可以将回调函数传递给createClient,如下所示:

function Thing(request, response) {

    this.foo = function() {
        console.log("this is foo");
    }

    this.sendSoap = function(err, client) {
        // Get SOAP args
        args = { 
            foo: this.request.cookies.foo <--- this.cookies undefined
        }; 
        client.doSomething(args, function(err, result) {
            // Somehow call foo(); <--- CAN'T FIND A WAY TO DO THIS
        });
    }

    this.doThing = function() {
        // From the SOAP npm package library
        soap.createClient(this.sendSoap);
    }
}
// Make it so I can access this.request and this.response somehow
Thing.prototype = Object.create(AbstractThing); 

我无法再访问 this.request.cookies,因为 this 现在在 sendSoap 闭包内被调用。我不知道为什么 javascript 将函数作为对象,但我有点沮丧。

我已经尝试了很多很多东西,但无法找到一种方法来做到这一点并且需要这样做,因为对 foo 的原始调用实际上是我在状态迭代器模式中使用的递归函数我用 Java 编写的 SOAP Web 服务中的身份验证。

我能想到的最后一种方法是修改 SOAP npm 包,以便我可以将 this.cookies 传递给 createClient 而不仅仅是回调。

我真的完全没有想法。任何帮助将不胜感激。

【问题讨论】:

    标签: javascript node.js asynchronous soap callback


    【解决方案1】:

    原因是回调函数中的this 通常会引用全局窗口范围。

    this 是 JS 开发人员的常见痛苦来源,而且通常它并不指代您认为可能发生的情况。您可以在线搜索完整的详细信息。

    为什么不这样关闭呢?

    function Thing(request, response) {
    
        this.foo = function() {
            console.log("this is foo");
        }
    
        this.doThing = function() {
            var self = this; //Closure to the Thing function
            // Get SOAP args
            args = { foo: this.request.cookies.foo };
            // From the SOAP npm package library
            soap.createClient(function(err, client) {
                client.doSomething(args, function(err, result) {
                    self.foo();
                });
            });
        }
    }
    

    【讨论】:

      【解决方案2】:

      一个可行的解决方案的多个选项。

      A.将嵌套函数声明为命名函数,或将匿名函数分配给闭包内的命名变量,允许闭包内的任何其他函数调用嵌套函数而不使用this例如

      // Either naming a function:
      function foo () { console.log("foo") 
      // or assigning it to a named variable:
      var foo = function() { console.log("foo")};
      

      允许函数在闭包内以foo() 的形式调用。

      B.在Thing 对象构造期间声明一个设置为this 值的变量允许闭包内的函数使用变量名称访问它们的实例对象。这与 Philip 的回答中包含的技术相同:

      `var self = this;`
      

      C.使用分配给命名变量的匿名arrow functions。可以使用变量名从闭包中的其他嵌套函数调用它们。箭头函数从声明它们的时间和位置绑定this 值。因此箭头函数可以使用this 访问它们的Thing 对象实例,而无需单独的self 变量别名。例如

      var foo = () => {console.log(this.message)};
      this.message = "foo was here";
      foo();  // logs 'foo was here'
      

      D.当然,将必须在闭包之外访问的任何参数、嵌套函数或数据值设置为对象属性。

      // inside constructor
         var foo = () => { /* whatever */ }; // callable within closure as foo()
         this.foo = foo;
      // outside constructor
         var thing = new Thing( arg1, arg2);
         thing.foo();                        // callable outside closure as thing.foo()
      

      E) 当作为构造函数调用时传递给Thing 的参数可以在闭包中通过使用参数名称来访问。要从请求 cookie 对象设置名称值对对象,您可能需要不带 thisobject initialiser

          args = { 
              foo: request.cookies.foo // request is a parameter
          };
      

      【讨论】:

      • 箭头函数的注意事项!
      猜你喜欢
      • 1970-01-01
      • 2013-06-21
      • 2014-09-13
      • 2016-05-02
      • 1970-01-01
      • 2016-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多