2017-02-25 100 views
0

在socket.io函數中,我在數據庫中創建新用戶並返回插入的id。但是我的函數在數據庫回調完成之前返回。所以,我得到了插入標識回客戶端:socket.io函數在回調完成前返回 - Node.js

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

提供回調createChatRoom funtion,以及從查詢的結果調用它。 – Edgar

回答

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

+0

我忘記提到我們在節點世界中使用稱爲「Error first」的模式來回調。這意味着如果有一個或null的話,回調的第一個參數應該是一個錯誤。你應該總是檢查這些錯誤類似於我的做法。 – eddiezane

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

};

+0

如何傳遞參數? –

+0

你可以在socket中創建回調。on'回調,所以你可以訪問你的變量 –

+0

可以使用上面的場景發佈示例代碼? –

0

正如Maria注意到的,您的新用戶處理程序包括髮出newUser事件。當你觸發newUser時,處理程序接管,所以此代碼「循環」。一些重構必須完成。同時,調用createChatRoom(通常)很慢,因爲它具有I/O。

NodeJS是非同步的。我倒是建議是同步的,就像

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 < 0.9

+0

我的版本是V6.9.2 –