在socket.io函数中我在DB中创建新用户并返回插入的id。但是我的函数在数据库回调完成之前返回。所以我在客户端获得了插入的ID:
io.on('connection',function (socket) {
socket.on('newUser',function (user) {
io.emit('newUser',createChatRoom(con,user.email,user.phone));
});
});
我的创建用户功能:
var createChatRoom = function (con, email, phone) {
con.query("SELECT * FROM USER WHERE `email`='" + email + "'", function (error, result) {
if (error) throw error;
if (result.length == 0) {
var chatToken = require('crypto').createHash('md5').update(email).digest("hex");
con.query("INSERT INTO user(email,chat_token,phone) VALUES('" + email + "','" + chatToken + "','" + phone + "')", function (error1, result1) {
return result1.insertId;
});
} else {
return "Old User";
}
});
};
答案 0 :(得分:1)
您遇到了一些异步JavaScript!
您使用con.query
拨打到您的数据库的电话实际上并没有像您认为的那样立即完成,因为它们就是我们所说的"非阻塞"。
网络请求是"非阻塞"并且可能需要一些未知的时间来完成。如果它是"阻止"操作程序会等待数据库的响应。你不能在JavaScript中阻止执行,因为一切都在幕后的一个大循环中运行。
为了解决这个问题,我们使用回调函数来发出请求"非阻塞"。你实际上已经在使用它们了!我们的想法是将function
作为参数传递给我们知道需要一些时间才能完成的操作。当潜在的长时间运行操作完成时,它会使用结果调用您的回调函数。
在代码中,query
运行后,将调用提供的回调函数。
con.query("INSERT INTO user(email,chat_token,phone) VALUES('" + email + "','" + chatToken + "','" + phone + "')", function (error1, result1) {
解决您的特定问题的方法是让您的createChatRoom
函数将回调作为参数。
io.on('connection',function (socket) {
socket.on('newUser',function (user) {
createChatRoom(con, user.email, user.phone, function (error, result1) {
if (error) {
// hanlde your error
// return
}
io.emit('newUser', result1);
})
});
});
var createChatRoom = function (con, email, phone, callback) {
con.query("SELECT * FROM USER WHERE `email`='" + email + "'", function (error, result) {
if (error) {
return callback(error);
}
if (result.length == 0) {
var chatToken = require('crypto').createHash('md5').update(email).digest("hex");
con.query("INSERT INTO user(email,chat_token,phone) VALUES('" + email + "','" + chatToken + "','" + phone + "')", function (error1, result1) {
if (error1) {
return callback(error1)
}
return callback(null, result1.insertId)
});
} else {
return callback(null, "Old User");
}
});
};
你可能需要稍微改变一下,但希望你能得到这个想法!
Here's a talk我就这个话题提出了一个blog post。
答案 1 :(得分:0)
<强>更新强>
由于io.emit只是发出带有消息的事件,您可以在套接字内部调用createChatRoom
,然后将io.emit
的行移到createChatRoom
的末尾
io.on('connection',function (socket) {
socket.on('newUser',function (user) {
createChatRoom(con,user.email,user.phone)
});
});
var createChatRoom = function (con, email, phone) {
con.query("SELECT * FROM USER WHERE `email`='" + email + "'", function (error, result) {
if (error) throw error;
if (result.length == 0) {
var chatToken = require('crypto').createHash('md5').update(email).digest("hex");
con.query("INSERT INTO user(email,chat_token,phone) VALUES('" + email + "','" + chatToken + "','" + phone + "')", function (error1, result1) {
io.emit('newUser',result1.insertId);
});
} else {
io.emit('newUser',"Old User");
}
});
};
答案 2 :(得分:0)
正如Maria所说,你的newUser处理程序包含newUser
事件的发出。当你解雇newUser
时,处理程序接管,所以这段代码“循环”。必须进行一些重构。同时,调用createChatRoom
(通常)因为它有I / O而缓慢。
NodeJS是natrue的异步。我建议的是同步,比如
io.on('connection',function (socket) {
socket.on('newUser',function (user) {
setImmediate(() => {
console.log('Do something (async)');
});
io.emit('newUser',createChatRoom(con,user.email,user.phone));
});
});
注意:setImmediate在NodeJS中不可用&lt; 0.9