NPM模块" deasync"没有使用Hapi JS for MySQL fetch

时间:2015-05-27 00:56:05

标签: javascript mysql node.js hapijs

问题的当前状态(深入研究许多问题后)

所以,归结为此。以下独立代码[不是项目的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之外的魅力一样......

1 个答案:

答案 0 :(得分:1)

作为deasync的原始作者,我强烈建议您(以及其他所有人)不要将它用于任何事情。它很脆弱,只适用于某些案例。

根本不应该在运行事件循环中工作:https://github.com/joyent/node/issues/7555#issuecomment-42295204