nodejs回调函数中的变量实例化

时间:2013-09-13 23:07:22

标签: node.js callback

我在nodeJS中有一个连接到我的postgres数据库的脚本,问题是在回调方法上我正在启动一个变量,但它似乎总是空的,这是我的app.js脚本:

var ck_username = /^[A-Za-z0-9_]{1,20}$/;
function fncCheckUsernameAvailability(vstrUsername, callback) {
    var pg = require("pg");
    var client = new pg.Client({user: 'xxx', password: 'xxx', database: 'xxx', host: 'xxx.com'});
    client.connect(function(err) {
    if (err) {
      callback(err, null);
      return;
    }
    client.query("SELECT username FROM users WHERE username ='"+vstrUsername+"'", function(err, result) {
      if (err) {
        callback(err, null);
        return;
      }
      if (result.rows[0] == undefined) {
            callback(null, null);
      }else {
            callback(null, 'Username already taken');
      }
    client.end();
    });
  });
}

app.post("/Signup", function(req, res){
var username = req.body.username;

var usernameError = '';  
var errors = [];

if (!ck_username.test(username)) {
    errors[errors.length] = "Invalid username";
    usernameError = "Invalid username";
} 
if (ck_username.test(username)) {
     //The issue starts here
    fncCheckUsernameAvailability(username, function(err, result) { 
        if(result != null){ 
        errors[errors.length] = result;
            usernameError = result; // usernameError  is always empty 
            console.log(result);//This is printed in console, I can see the result
        }
    });
}
if (errors.length > 0) {
     res.render('Signup.ejs', {
        layout:false,
        usernameError:usernameError // usernameError is sent to the view empty            
    });
}
else{
    res.render('Signup.ejs', {
        layout:false,
        usernameError:'No errors'
    });
} 
});

结果显示在cansole上,所以有人可以告诉我为什么这个变量没有实例化,这个回调是异步的吗?

2 个答案:

答案 0 :(得分:2)

  

这个回调是异步回调吗?

//This line executes at time 1
if (ck_username.test(username)) {
     //The issue starts here
    fncCheckUsernameAvailability(username, function(err, result) {
        //this section of code executes at time 3! Oh snap async blew my mind! 
        if(result != null){ 
        errors[errors.length] = result;
            usernameError = result; // usernameError  is always empty 
            console.log(result);//This is printed in console, I can see the result
        }
    });
}
//This section of code executes at time 2 which is BEFORE time 3
if (errors.length > 0) {
     res.render('Signup.ejs', {
        layout:false,
        usernameError:usernameError // usernameError is sent to the view empty            
    });
}

您必须移动所有需要result变量INSIDE该回调函数的代码。将它放在函数之外但在文件中较低会使事情以错误的顺序执行。

同时结帐http://callbackhell.com以获取有关在异步环境中调整代码组织的指导。

答案 1 :(得分:1)

是的,回调是异步的,可以随时执行。可能在您访问时尚未定义。因此,您应该从回调内部访问变量,因此将始终在该点定义它。

app.post('/Signup', function (req, res) {
  var username = req.body.username;

  if (!ck_username.test(username)) {
    res.render('Signup.ejs', {
      layout: false,
      usernameError: 'Invalid username'          
    });
  } else {
    fncCheckUsernameAvailability(username, function (err, result) {
      if (result != null) {
        res.render('Signup.ejs', {
          layout: false,
          usernameError: result            
        });
      } else {
        res.render('Signup.ejs', {
          layout: false,
          usernameError: 'No errors'
        });
      }
    });
  }
});

以下是回调如何工作的示例,以及您的变量未返回预期值的原因。采取这两个功能:

var foo = function(num, callback) {
  setTimeout(function() {
    callback(num * 2);
  }, 5000);
};

此功能将数字乘以2,但在5秒后。如果您尝试在5秒之前访问变量,则没有值,例如:

var num = 0;
foo(5, function(result) {
  num = result;
});

console.log(num); // returns 0

在这种情况下,num仅在5秒后设置为10console.log()将在该时间过去之前执行。