简体   繁体   English

Node.js从回调函数中提取值

[英]Node.js extract value from callback function

I have a server file with a switch using the URL to display appropriate content. 我有一个服务器文件,其中有一个使用URL来显示适当内容的开关。 One of the cases is /users which should display a JSON string of a certain table. 一种情况是/ users,它应该显示某个表的JSON字符串。 This is returned from a mysql file. 这是从mysql文件返回的。

server.js server.js

var http = require('http')
var url = require('url')
var port = 8080

function onRequest(request, response) {
    var pathname = url.parse(request.url).pathname
    console.log('Request for ' + pathname + ' received.')

    response.writeHead(200, {'Content-Type': 'text/html'})
    response.write(run(pathname))
    response.end()
}

function run(pathname) {
    switch(pathname) {
        case '/':
            response = 'Welcome to my little test'
            break
        case '/time':
            response = 'The time is ' + new Date().toLocaleTimeString()
            break
        case '/users':
            var response
            require('./mysql').getUsers(function(users) {
                console.log(users)
                response = users
            })
            return response
            break
        default:
            response = 'Unable to locate the requested page'
    }
    return response
}

http.createServer(onRequest).listen(port)
console.log('Server started on port ' + port + '.')

mysql.js mysql.js

var mysql = require('mysql')

var connection = mysql.createConnection({ 
    user: "root", 
    password: "password", 
    database: "main"
})

exports.getUsers = function(callback) {
    connection.query('SELECT * FROM users;', function (error, rows, fields) {
        callback(JSON.stringify(rows));
    });
};

The console.log(users) in server.js displays the JSON string fine, but I cannot figure out how to get the value out of the callback and into the response variable. server.js中的console.log(users)可以很好地显示JSON字符串,但是我无法弄清楚如何从回调中获取值并放入响应变量中。

Any ideas will be greatly appreciated. 任何想法将不胜感激。

The way you could extract the value out of the callback is to assign that value to a variable out of the callback's scope, but I don't recommend you to do that since you would end up with lots of global variables, besides you don't know when the variable will be assigned. 您可以从回调中提取值的方法是将该值分配给回调范围之外的变量,但是我不建议您这样做,因为您最终会得到很多全局变量,除了不知道何时分配变量。 Try this and see what happens so you get some insight with how callbacks and node.js works: 尝试一下,看看会发生什么,以便您对回调和node.js的工作方式有一些了解:

function run(pathname) {
    switch(pathname) {
        case '/':
            response = 'Welcome to my little test'
            break
        case '/time':
            response = 'The time is ' + new Date().toLocaleTimeString()
            break
        case '/users':
            var response
            var out_of_callback_users
            require('./mysql').getUsers(function(users) {
                out_of_callback_users = users
                console.log("In the callback")
                console.log(users)
                response = users
            })
            console.log("After require");
            console.log(out_of_callback_users) //Users have not been assigned yet
            setTimeout(function(){
              console.log("In the timeout") 
              console.log(out_of_callback_users)
            },5000) //After 5 secs the query has been completed and users have been assigned.
            return response
            break
        default:
            response = 'Unable to locate the requested page'
    }
    return response
}

The way I would go is something like this: 我要走的路是这样的:

function onRequest(request, response) {
    var pathname = url.parse(request.url).pathname
    console.log('Request for ' + pathname + ' received.')

    response.writeHead(200, {'Content-Type': 'text/html'})
    run(pathname, function(response){
      response.write(response)
      response.end()
    })
}

function run(pathname,cb) {
    switch(pathname) {
        case '/':
            cb('Welcome to my little test');
            break;
        case '/time':
            cb('The time is ' + new Date().toLocaleTimeString());
            break;
        case '/users':
            require('./mysql').getUsers(function(users) {
                console.log(users);
                cb(users);
            })
            break;
        default:
            cb('Unable to locate the requested page');
    }
    return;
}

http.createServer(onRequest).listen(port)
console.log('Server started on port ' + port + '.')

You do not need to serialize the mysql returned rows to use it. 您无需序列化mysql返回的rows即可使用它。 Either you can process it within getUsers , or return it back to the controller. 您可以在getUsers中对其进行处理,也可以将其返回给控制器。 If you return it, change code to: 如果返回,请将代码更改为:

exports.getUsers = function(callback) {
    connection.query('SELECT * FROM users;', function (error, rows, fields) {
        callback(rows);
    });
};

Now within the server.js file, you can process the returned rows, like: 现在,在server.js文件中,您可以处理返回的行,例如:

case '/users':
  var response = ''
  require('./mysql').getUsers(function(users) {
    for (var i in users) {
      var user = users[i];
      var userId = user.id;
      var userName = user.user_name;
      response += "User - ID: "+userId+" Name: "+userName+"\n";
    }
  })
  return response;
break;

You can process 您可以处理

you can't do it like this. 你不能这样做。 the problem is easy. 问题很容易。 let's talk about it: function getUsers is an asynchronous. 让我们来谈谈: getUsers函数是异步的。 so the code follow runs like this: 因此代码遵循如下运行:

 case '/users':
   var response
   require('./mysql').getUsers(function(users) {
     console.log(users)
     response = users
   })
   return response
   break

first, run require('./mysql').getUser() , then it will do return response directly, then break . 首先,运行require('./mysql').getUser() ,然后它将直接return response ,然后break when the getUser function is finished, it will run getUser函数完成时,它将运行

 function(users) {
     console.log(users)
     response = users
   })

so, a rule you need to follow: once you use asynchronous, the other function have to be asynchronous. 因此,您需要遵循一条规则:一旦使用异步,其他功能就必须异步。 i wonder you can modify like follow: 我不知道您可以修改如下:

function onRequest(request, response) {
  var pathname = url.parse(request.url).pathname
  console.log('Request for ' + pathname + ' received.')

  response.writeHead(200, {'Content-Type': 'text/html'})
  run(pathname, function(res){ response.write(res)})  //changed
  response.end()
}

function run(pathname, callback) {
  switch(pathname) {
      case '/':
        callback('Welcome to my little test')
        break
      case '/time':
        callback('The time is ' + new Date().toLocaleTimeString())
        break
      case '/users':
        var response
        require('./mysql').getUsers(function(users) {
            console.log(users)
            callback(users) # changed
        })
        break
      default:
        callback('Unable to locate the requested page')
  }
}

http.createServer(onRequest).listen(port)
console.log('Server started on port ' + port + '.')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM