0

我在 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上,所以有人可以告诉我为什么这个变量没有实例化,这个回调是异步的吗?

4

2 回答 2

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回调函数内部变量的代码。将它放在函数之外但在文件中的较低位置会使事情以错误的顺序执行。

另请查看http://callbackhell.com以获取有关在异步环境中调整代码组织的指导。

于 2013-09-13T23:16:00.553 回答
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仅设置为105 秒后,console.log()将在该时间过去之前执行。

于 2013-09-13T23:14:06.780 回答