我在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上,所以有人可以告诉我为什么这个变量没有实例化,这个回调是异步的吗?
答案 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秒后设置为10
,console.log()
将在该时间过去之前执行。