socket.io函数在回调完成之前返回 - Node.js

时间:2017-02-25 18:24:51

标签: javascript node.js sockets express

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

3 个答案:

答案 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