问题的当前状态(深入研究许多问题后)
所以,归结为此。以下独立代码[不是项目的prt]在使用简单节点工作时无法在Hapi JS中运行。
var Deasync = require('deasync');
var Hapi = require('hapi');
var mysql = require('mysql');
var server = new Hapi.Server();
server.connection({ port: 4000 });
var someAsyncFunction = function () {
var connection, done, preCoins;
console.log("fetchPreCoins called!");
connection = mysql.createConnection({
host: 'xx.xx.xx.xx',
port: 3306,
user: 'xxx',
password: 'xxxx',
database: 'db_xxx'
});
connection.connect();
preCoins = null;
done = false;
console.log("Just before connection!");
connection.query('SELECT preCoins from tbl_nzk_user_orbs WHERE userId = "' + "abc" + '"', function(err, rows, fields) {
if (err) {
console.log("MySQL DB Failed!");
}
if (!rows[0]) {
connection.end();
preCoins = null;
done = true;
console.log("Did not find");
} else {
connection.end();
preCoins = rows[0].preOrbs;
done = true;
}
});
require('Deasync').loopWhile(function() {
return !done;
});
console.log("fetchPreCoins about to return");
return preOrbs;
};
server.route({
method: 'GET',
path: '/',
handler: function (request, reply) {
reply(someAsyncFunction());
}
});
server.start(function () {
console.log('Started server!');
});
原始问题: 我有一个奇怪的场景,如果我将它放在一个独立的文件中并使用Node运行它,我的Coffee Script的输出代码就可以工作。但是当它在使用HAPI JS编写的restful API服务器中的路径内时无法运行。
首先,要了解用例;已经有一个庞大的代码库,这是一个额外检查的后期添加。我基本上没时间重构所有内容并以默认的异步方式使用它。
经过一番研究,我正在使用精彩的npm模块" deasync"。以下是Coffee编译的输出代码,是否存在配置问题或阻止HAPI向此外部服务器发出请求的内容。终端控制台上没有任何错误或任何错误,它只是冻结然后超时:
mysql = require('mysql');
deasync = require('deasync');
fetchPreCoins = function(userId) {
var connection, done, preCoins;
console.log("fetchPreCoins called!");
connection = mysql.createConnection({
host: 'xx.xx.xx.xx',
port: 3306,
user: 'xxxx',
password: 'xxxxx',
database: 'xxxx'
});
connection.connect();
preCoins = null;
done = false;
console.log("Just before connection!");
connection.query('SELECT preCoins from tbl_xxx WHERE userId = "' + userId + '"', function(err, rows, fields) {
if (err) {
console.log("MySQL DB Failed!");
}
if (!rows[0]) {
connection.end();
preCoins = null;
done = true;
console.log("Did not find");
} else {
connection.end();
preCoins = rows[0].preCoins;
done = true;
}
});
require('deasync').loopWhile(function() {
return !done;
});
console.log("fetchPreCoins about to return");
return preCoins;
};
当使用Node执行时,调用它就像在外部JS文件中完美地工作:
fetchPreCoins();
软件包正确包含在shrinkwrap中,并为我的基于HAPI的API服务器安装。但是,最后一个日志是"就在连接之前!"这是卡住和超时的地方。我真的需要这种方法同步或基本上等待来自MySQL服务器的响应并返回值。
如果是HAPI路线,我只是称之为:preCoins = Helpers.fetchPreCoins(userId)
我在外部文件中尝试了同样的事情:
value = fetchPreCoins(userId);
console.log("Value is: " + value);
该函数正确返回。如何使用Hapi JS完成这项工作。 Node's MySQL module和HAPI之间是否存在兼容性问题?我看了hapi-mysql,但我认为这也解决了。
这是HAPI路由代码[CoffeeScript]的一个子集,除了调用此方法被卡住的时候,它才能正常工作。
method: 'POST'
path: '/sessions/users'
config:
description: 'Create session/get token (login) for a user'
auth: false
validate:
payload:
password: Joi.string().required()
username: Joi.string().regex(Models.usernameRegex).lowercase().trim()
pre:
[
assign: 'user'
method: (request, next) ->
Models.User.findOne(username: request.payload.username, '+passwordHash +passwordHashSalt').execute(next)
,
(request, next) ->
Helpers.passwordCheck(request.payload.password, request.pre.user.passwordHashSalt, request.pre.user.passwordHash, next)
# TODO: Could reset shared secret to improve security
]
handler: (request, reply) ->
prevDate = new Date(request.pre.user.lastSeen).setHours(0,1,0)
if (Helpers.timeDifference(prevDate, 60) >= 24)
if request.pre.user.experience < 100
addAmount = 4
else if request.pre.user.experience >= 100 and request.pre.user.experience < 1000
addAmount = 7
else if request.pre.user.experience >= 1000 and request.pre.user.experience < 4000
addAmount = 10
else if request.pre.user.experience >= 4000 and request.pre.user.experience < 10000
addAmount = 13
else if request.pre.user.experience >= 10000
addAmount = 16
else
addAmount = 3 # this should not happen though!
if request.pre.user.membership != "free"
addAmount += 10 # extra bonus for members
console.log "user Id: ", request.pre.user.id
preCoins = Helpers.fetchPreCoins(request.pre.user.id)
console.log "Pre coins fetched: ", preCoins
if preCoins != null
if preCoins == request.pre.user.coins
request.pre.user.coins += addAmount
else
request.pre.user.coins = preCoins + addAmount # the case when bug had occured and this reverts it
else
request.pre.user.coins += addAmount
Helpers.writePreCoins(request.pre.user.id, request.pre.user.coins)
Helpers.updateNotification("continuous-day-member-coins", request.pre.user.notifications, request.pre.user)
Helpers.updateNotification("continuous-day-coins", request.pre.user.notifications, request.pre.user)
request.pre.user.lastSeen = Date.now()
request.pre.user.store()
reply(request.pre.user.toObject(transform: true))
更新 为了测试,我停止了&#34; deasync&#34;片刻,在HAPI API控制台上,我收到此超时错误。我无法弄清楚为什么会发生这种情况,因为它是一个非常简单的选择查询:
11:02:16 web.1 | Debug: hapi, internal, implementation, error
11:02:16 web.1 | Error: connect ETIMEDOUT
11:02:16 web.1 | at Connection._handleConnectTimeout (/Users/nikhilkhullar/Desktop/hapi-server/node_modules/mysql/lib/Connection.js:358:13)
11:02:16 web.1 | at Socket.g (events.js:180:16)
11:02:16 web.1 | at Socket.emit (events.js:92:17)
11:02:16 web.1 | at Socket._onTimeout (net.js:326:8)
11:02:16 web.1 | at Timer.unrefTimeout [as ontimeout] (timers.js:427:13)
更新2: 我发现实际的问题不是MySQL,因为即使写入也是异步的。所以,它深入到模块deasync的事实 不能在Hapi JS中使用。但是,遗憾的是,这使得这个获取代码毫无用处。有没有办法让这个函数现在等待回复,即基本上使connection.query同步行为。
尽管如此,同样的&#34; deasync&#34;就像Hapi JS之外的魅力一样......
答案 0 :(得分:1)
作为deasync的原始作者,我强烈建议您(以及其他所有人)不要将它用于任何事情。它很脆弱,只适用于某些案例。
根本不应该在运行事件循环中工作:https://github.com/joyent/node/issues/7555#issuecomment-42295204