【问题标题】:NPM module "deasync" not working with Hapi JS for MySQL fetchNPM 模块“deasync”不能与 Hapi JS 一起用于 MySQL fetch
【发布时间】:2015-06-16 18:38:24
【问题描述】:

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

所以,归根结底。以下独立代码 [不是项目的一部分] 在使用简单 Node 时无法在 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!');
});

原问题: 我有一个奇怪的场景,如果我将 Coffee Script 的输出代码放在一个独立的文件中并使用 Node.js 运行它,它就可以工作。但是当它在使用 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();

这些包正确地包含在收缩包装中,并为我的基于 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)) 

更新: 只是为了测试,我暂时停止了“deasync”,在 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 同步运行。

虽然,令人遗憾的是,同样的“deasync”在 Hapi JS 之外就像一种魅力......

【问题讨论】:

  • 你能发布 hapi 代码,或者它的最小子集,它代表你如何将此代码与 hapi 一起使用?如果上面的代码有效,我怀疑你发布的代码中没有显示问题。
  • 完成。 Helpers 是另一个包含在顶部的文件,并且没有问题,因为函数调用确实开始但永远不会超出 connection.query 点...
  • hapi 并没有排除使用 deasync 模块。例如,此示例适用:gist.github.com/mtharrison/de928de66d89f812f859
  • 也不太明白你“没有时间做异步”的评论。给你的函数添加回调参数有多难? Deasync 对我来说似乎是个糟糕的主意。
  • 听起来您在连接 MySQL 时遇到问题。在此处尝试显式的connect() 方法:github.com/felixge/node-mysql/#establishing-connections 以检查是否有任何错误。

标签: javascript mysql node.js hapijs


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 2017-09-29
    • 2019-04-10
    • 2017-10-17
    • 2021-01-03
    • 1970-01-01
    • 2011-08-20
    • 2017-11-12
    • 2021-02-13
    • 2016-08-31
    相关资源
    最近更新 更多