【问题标题】:nodejs express: store parameters in variablenodejs express:将参数存储在变量中
【发布时间】:2015-01-12 05:48:51
【问题描述】:

我还是 nodejs 的新手,仍然不知道如何访问函数中的变量并回调该变量。

检查几个链接:但我真的很困惑。请帮忙!

Node.JS: How to pass variables to asynchronous callbacks?

How can we access variable from callback function in node.js?

var express = require('express');
var app = express();
var router = express.Router(); 
var https = require('https').createServer( ssl_options, app);
var io = require('socket.io')( https );
**var user_id;
var room_id;**

router.use(function(req, res, next) {
    next(); 
});

app.use('/chat',router);

router.route( '/chat/:user_id/:room_id' )
.get(function(req,res){

    res.sendFile( __dirname + '/index.html' );

    user_id = req.param('user_id');
    room_id = req.param('room_id');

});

https.listen(3000);

io.on('connection', function(socket){

  **console.log ( user_id );
  console.log ( room_id );**


});

【问题讨论】:

    标签: javascript node.js socket.io


    【解决方案1】:

    不确定如何访问函数中的变量并回调该变量。

    这里有一些规则:

    1。函数内声明的变量是函数的*局部*。

    以下是函数的本地含义示例:

    function do_stuff() {
        var x = 10;
    }
    
    do_stuff();
    console.log(x); 
    
    1. x 在函数执行之前不存在。
    2. 函数执行完毕后,x 被销毁并不再存在。

    因此,console.log(x); 行会产生错误:

    ReferenceError: x is not defined
    

    在您的第二个链接中提出问题的人不明白,一旦函数完成执行,局部变量就会被销毁,因此在声明了用户名变量的匿名函数之外的任何地方都无法访问其代码中的用户名变量。

    另一方面,如果你不使用 var 声明变量,那么 javascript 会创建一个全局变量:

    function do_stuff() {
      x = 10;
    }
    
    do_stuff();
    console.log(x);  //=>10
    

    相当于写:

    var x;
    
    function do_stuff() {
      x = 10;
    }
    
    do_stuff();
    console.log(x);  //=>10
    

    通常认为函数在函数外部操作变量的值是不好的做法。您应该更喜欢以下内容:

    function do_stuff() {
      return 10;
    }
    
    var x = do_stuff();
    

    在您的情况下, express 将调用您的匿名函数,而 express 只是丢弃任何返回值。大概,express 做了这样的事情:

    function express_get(func) {
      console.log("express_get is executing");
      requ = {greeting: 'hello'};
      resp = {};
    
      func(requ, resp); //Anything returned by func is not captured in a variable
    }
    
    //Here is an attempt to call express_get() and return 
    //the data rather than setting a global variable:
    express_get(function(requ, resp) {
      console.log("my callback is executing");
      console.log(requ);
      return {user_id: 1, room_id: 'A'};
    });
    
    
    --output:--
    express_get is executing
    my callback is executing
    { greeting: 'hello' }
    

    因为 express 正在调用您的请求处理函数,并且由于 express 只是丢弃任何返回值,因此无法访问您从请求处理函数返回的值。

    也许您正在以错误的方式思考问题?与其试图弄清楚如何将请求数据获取到 io.on('connect') 代码中,不如考虑如何在路由处理函数中获取 io.on('connect') 代码。如果你这样做会发生什么:

    router.route(...).get(function(req,res){
    
      user_id = req.param('user_id');
      room_id = req.param('room_id');
    
      io.on('connection', function(socket){
        console.log ( user_id );
        console.log ( room_id );
      });
    
    });
    

    根据此答案中讨论的所有规则,您应该尝试确定:

    1. 传递给get()的匿名函数内的代码能否看到io变量?
    2. 传递给 io.on() 的匿名函数内的代码能否看到 user_id 和 room_id 变量?

    2。函数的参数变量也是函数的局部变量。

    这是一个例子:

    function do_stuff(x) {
      console.log(x);  //=>hello
    }
    
    do_stuff("hello");
    console.log(x);  //=>ReferenceError: x is not defined
    

    所以 x 在函数执行之前不存在,而 x 在函数执行完成时不再存在。

    3。在 for 循环中声明的变量不是 for 循环的本地变量。

    这是一个例子:

    function do_stuff() {
    
      for (var x=0; x < 10; ++x) {
        console.log(x);
      }
    
      console.log(x) //=>10
    }
    
    do_stuff();
    

    您可以等效地(更清楚地)编写上面的函数,如下所示:

    function do_stuff() {
      var x;
    
      for (x=0; x < 10; ++x) {
        console.log(x);
      }
    
      console.log(x)  //=> 10
    }
    
    do_stuff();
    

    4。函数内部的代码可以看到在函数*定义*时存在于函数外部范围内的变量。

    这是一个例子:

    var x = 10;
    
    function do_stuff() {
        console.log(x); 
    }
    
    do_stuff();  //=>10
    

    很简单。 周围的范围的意思是:

    //First line of program
          ^
          |
          | part of do_stuff() surrounding scope
          |   
          v
    ------------------------+
    function do_stuff() {   |
       //Do stuff           |
    }                       |
    ------------------------+
          ^
          | part of do_stuff() surrounding scope
          |
          v
    ---------------------------+
    function other_func() {    |
                               |
                               |
      //Do other stuff         |
                               |
    }                          |
    ---------------------------+
          ^
          | part of do_stuff surrounding scope
          |
          v
    //Last line of program
    

    请注意,other_func 内的代码区域不是 do_stuff 周围范围的一部分,因此 do_stuff 内的代码无法看到 other_func 内声明的变量。

    使用嵌套函数,周围的范围如下所示:

    ^  part of inner's surrounding scope
    |
    |
    function outer() {
            ^
            | part of inner's surrounding scope
            |
            v
    ----------------------+
      function inner() {  |
                          |
      }                   |
    ----------------------+
            ^
            | part of inner's surrounding scope
            v
    --------------------------+  
      function other_inner {  |
                              |
      }                       |
    --------------------------+
            ^
            | part of inner's surrounding scope
            |
            V
    }
    |
    |
    V
    part of inner's surrounding scope
    

    这是一个例子:

    var x = 10;
    
    function outer() {
    
      function inner() {
        console.log(x);
      }
    
      inner();
    }
    
    outer();  //=>10
    

    对于定义为函数参数的匿名函数,例如:

    some_func(10, 20, function(req, resp) {.....});
    

    这和写这个几乎是一样的:

    function request_handler(req, resp) {
      //Do stuff
    }
    
    some_func(10, 20, requestHandler);
    

    您可以使用上图之一确定 request_handler 函数的周围范围。

    在计算机科学术语中,javascript 函数被称为 closures,并且 javascript 函数被称为 关闭 函数当时存在的周围范围内的变量已定义。如果您正在阅读说明某个函数是 闭包 的内容,您可以对自己耳语,“当函数执行时,它可以看到在定义函数时存在的周围范围内的变量。”

    这是一个更复杂的例子:

    function outer() {
        var x = 10;
    
        function inner() {
          console.log(x);
        }
    
        return inner;
    }
    
    func = outer();
    
    //outer() has finished executing here.
    
    func();
    

    从规则 1 开始,你可能期望在 outer() 执行完成后 x 会被销毁,因此当 inner() 通过 func() 执行时,你会得到一个未定义的错误。然而,事实并非如此。 inner() 仍然可以看到 x,即使通常 x 在 outer() 完成执行时会被销毁。当inner被定义时,inner()被称为关闭存在于周围范围内的变量。

    这是另一个例子:

    function outer() {
        var x = 10;
    
        function inner() {
          console.log(x);
        }
    
        return inner;
    }
    
    
    func = outer();
    
    //outer() has finished executing here.
    
    var x = 20;  //New code
    func();
    

    那里的输出是什么? 20?没有。 inner() 函数在 定义 时查看周围作用域中的变量,而不是在 执行 时查看周围作用域中的变量。

    最后一个例子:

    function outer() {
      var funcs = [];
    
      for(var x=0; x < 10; ++x) {
    
        function inner() {
          console.log(x);
        }
    
        funcs.push(inner);
      }
    
      return funcs;
    }
    
    ten_funcs = outer();
    
    for(var y=0; y < 10; ++y) {
      ten_funcs[y]();
    }
    

    你认为输出会是什么?事实证明,十个函数中的每一个都输出 10。这表明函数关闭 变量——而不是值。我们知道我们可以像这样重写外部:

    function outer() {
      var funcs = [];
      var x;
    
      for(x=0; x < 10; ++x) {
    
        function inner() {
          console.log(x);
        }
    
        funcs.push(inner);
      }
    
      return funcs;
    }
    

    因此,十个函数中的每一个都看到相同的 x 变量。函数定义好后,给周围作用域能看到的x变量赋一个新值,然后每一个ten_funcs执行的时候,都能看到变量x,最后赋给x的值是10。在您的第一个链接中提出问题的人对变量范围的这一方面以及函数内的代码可以看到哪些变量感到困惑。

    唯一需要解释的是“隐藏”:

    var x = 20;
    
    function do_stuff() {
      var x = 10;
      console.log(x);
    }
    
    do_stuff(); //=>10
    

    这是规则 4 的一个例外。在函数内部,如果您声明一个与函数周围作用域中的变量同名的变量,javascript 会创建一个新的局部变量来隐藏周围作用域中的变量。

    【讨论】:

    • 非常感谢您的解释!它澄清了更多关于全局变量的信息。但就我而言,我需要用函数包装 router.get 吗? function express_get(funct){ router.route().get(function(){}) } ?
    • @tonoslfx,抱歉,我很忙,没有时间为您的问题提出解决方案。请参阅规则 1 末尾添加的文本。
    猜你喜欢
    • 2023-04-06
    • 2012-11-19
    • 2018-07-15
    • 2019-03-23
    • 2015-08-06
    • 1970-01-01
    • 1970-01-01
    • 2021-01-20
    • 1970-01-01
    相关资源
    最近更新 更多