我正在为私人消息系统编写后端API,我遇到了编写我的一个函数的问题。我需要保存对变量的异步调用的响应,以便在所述异步调用之外使用。
在进一步解释之前,我会提供代码:
app.get("/api/users/:UserID/messages/deletemessage/:MessageID", function(req, res){
var messageID = parseInt(req.params.MessageID);
var message = null;
connection.query("SELECT * FROM Message WHERE MessageID = ?", messageID, function(err, resp){
if(!err){
message = resp[0];
}
});
console.log(message);
//continue using the message variable here to perform more functionality...
});
您可以看到我正在尝试将message
变量分配给mysql数据库的select查询的响应。
当该功能运行时,null
将被打印到屏幕上。我知道为什么会发生这种情况,这是因为在完成对数据库的查询之前调用了console.log
语句。
我的问题是,如何修复此问题以使用数据库查询范围之外的消息变量?
我只尝试了这个,但没有奏效:
app.get("/api/users/:UserID/messages/deletemessage/:MessageID", function(req, res){
var messageID = parseInt(req.params.MessageID);
var message = null;
connection.query("SELECT * FROM Message WHERE MessageID = ?", messageID, function(err, resp){
if(!err){
connection.end(); //try to end the connection so hopefully it assigns
message = resp[0];
}
});
console.log(message);
//continue using the message variable here to perform more functionality...
});
答案 0 :(得分:0)
在Node.js中,您必须将日志语句移动到查询函数中,其中message
变量已分配。
Node不会在记录之前等待该查询完成。节点只是将数据从一个地方传送到另一个地方,它并没有真正等待或“锁定”#34;因为它是一种异步语言。
所以绕过它的方法是将一个函数调用到另一个函数中,在另一个函数内调用另一个函数,你可能认为这会变得混乱而且确实如此。它被称为callback hell。
有各种各样的方法,许多已成为今天的标准。回调函数变得非常混乱,导致回调地狱,所以只需使用Promise Chains或Yield expressions。
Yield表达式适用于生成器函数。它们基本上是*
之后function
的常规函数,如下所示:
function* () {
// generator function
// you can use the "yield" keyword here
}
请记住,Node.js默认不解释生成器函数。您必须使用co这样的模块来运行它们。
co非常简单易用。只需将生成器函数放在co函数中,它就可以工作。像这样:
var co = require('co');
co(function* () {
// you can yield here
});
所以你的代码看起来像这样:
var co = require('co');
app.get("/api/users/:UserID/messages/deletemessage/:MessageID", function(req, res){
co(function* () {
var messageID = parseInt(req.params.MessageID);
var resp = yield connection.query("SELECT * FROM Message WHERE MessageID = ?", messageID);
// NOTE THE YIELD ^
var message = resp[0];
console.log(message);
});
});
关于yield表达式和生成器函数需要考虑的一些事项:
co
只是Node v4.x及其下的生成器函数解释器,Node v6.x开箱即用地解释了生成器函数,因此您不需要它。co
的数据库模块,或者将https://www.npmjs.com/package/mysql-promise等承诺替换为任何其他模块,您只能使用如果他们支持承诺或co
app.get
替换了^Z
中的函数。因此,您可以直接在请求函数内部生成。