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

时间:2013-12-24 12:17:45

标签: javascript mysql node.js asynchronous callback

我有一个带有交换机的服务器文件,使用URL来显示适当的内容。其中一个案例是/ users,它应该显示某个表的JSON字符串。这是从mysql文件返回的。

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

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

server.js中的console.log(users)显示JSON字符串很好,但我无法弄清楚如何从回调和响应变量中获取值。

任何想法都将不胜感激。

3 个答案:

答案 0 :(得分:2)

你可以从回调中提取值的方法是将该值分配给回调范围之外的变量,但我不建议你这样做,因为你最终会得到很多全局变量,除此之外你不知道什么时候会分配变量。试试看看会发生什么,这样你就可以了解回调和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
}

我的方式是这样的:

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 + '.')

答案 1 :(得分:0)

您不需要序列化返回的rows mysql来使用它。您可以在getUsers内处理它,也可以将其返回给控制器。如果您将其返回,请将代码更改为:

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

现在在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;

您可以处理

答案 2 :(得分:0)

你不能这样做。问题很简单。让我们来谈谈它: function getUsers是异步的。所以代码遵循如下:

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

首先,运行require('./mysql').getUser(),然后直接执行return response,然后breakgetUser函数完成后,它将运行

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

所以,你需要遵循一条规则:一旦你使用异步,另一个函数必须是异步的。 我想你可以修改如下:

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 + '.')