是否可以在 Node.js 中监听对象实例化?

编程入门 行业动态 更新时间:2024-10-07 08:25:29
本文介绍了是否可以在 Node.js 中监听对象实例化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时送ChatGPT账号..

我正在 Node.Js 中开发一个浏览器游戏,我有这个脚本:

<块引用>

game.js >>

var config = require('./game_config.js');var mysql = require('mysql');var app = require('express')();var http = require('http').Server(app);var io = require('socket.io')(http);var connexion = mysql.createConnection({主机":config.DB_HOST,'用户':config.DB_USER,'密码':config.DB_PASS,数据库":config.DB_NAME});var Player = require('./server/class.player.js');io.on('connect', function(socket) {console.log('Co');播放器socket.on('登录', 函数(数据) {connexion.query("SELECT * FROM player WHERE nick = '"+data.login+"' AND pass = '"+data.pass+"'", function(err, rows) {如果(错误){抛出错误;} 别的 {如果(行.长度== 0){var dataRet = "LOG";socket.emit('登录', dataRet);} 别的 {var p = 行[0];var dataRet = new Player(p.id, p.nick, p.map_id, p.x, p.y, connexion).toJson();控制台日志(dataRet);}//没有 setTimeout 它将无法工作,因为对象没有时间实例化设置超时(功能(){socket.emit('登录', dataRet);},1000);}});});socket.on('disconnect', function(socket) {console.log('Disco');});});

<块引用>

class.Player.js >>

var Player = function (id, name, map_id, x, y, connexion) {this.id = id;this.name = 名称;this.map_id = map_id ;this.x = x;这.y = y;this.link = 连接;this.toJson = 函数 () {返回 {'id' : this.id,'name' : this.name,'map_id' : this.map_id,'x' : this.x,'y' : this.y};}}module.exports = 用户;

所以基本上,由于 game.js 中的setTimeout()"(用于 socket.emit() 事件),我的代码运行良好.如果我不使用它,由于 Node.js 的异步性,对象 'dataRet' 没有时间实例化,因此套接字发出未定义"或空".

所以我在想,必须有一种方法来侦听对象实例化,以便在完成后立即通过 socket.io 发出它.

解决方案

警告:SQL 注入漏洞

这与您的问题本身无关,但这很重要-您有一个巨大的SQL 注入 漏洞,任何人都可以对您的数据库进行任何操作.

代替:

connection.query(SELECT * FROM player WHERE nick = '"+ data.login + "' AND pass = '" + data.pass + "'",函数(错误,行){//...});

要么使用:

connection.escape(data.login)connection.escape(data.pass) 代替 data.login>data.pass

或:

connection.query("SELECT * FROM player WHERE nick = ? AND pass = ?", [data.login, data.pass],函数(错误,行){//...});

它不仅更安全,而且实际上更易于阅读和理解.请参阅:转义查询值/github/felixge/node-mysql#readme" rel="nofollow noreferrer">node-mysql 手册.

答案

现在,回到你的问题.您的 Player 构造函数没有任何异步内容,因此您的问题一定是其他问题.奇怪的是,您的 Player.js 导出 User(未定义)而不是 Player(已定义),所以我很惊讶它甚至可以工作.或者,您发布的代码可能与您实际使用的代码不同,这可以解释为什么您存在代码中不明显的竞争条件.

但是如果您的 Player 构造函数进行了一些异步调用,那么我建议添加一个回调参数并从构造函数中调用它:

var Player = function (id, name, map_id, x, y, connexion, callback) {this.id = id;this.name = 名称;this.map_id = map_id ;this.x = x;这.y = y;this.link = 连接;this.toJson = 函数 () {返回 {'id' : this.id,'name' : this.name,'map_id' : this.map_id,'x' : this.x,'y' : this.y};}//一些你必须等待的异步调用//用 setTimeout 符号化:setTimeout(function () {if (callback && typeof callback === 'function') {回调(这个);}}, 1000);}

然后您可以将回调传递给您的构造函数,因此:

 } else {var p = 行[0];var dataRet = new Player(p.id, p.nick, p.map_id, p.x, p.y, connexion).toJson();控制台日志(dataRet);}//没有 setTimeout 它将无法工作,因为对象没有时间实例化设置超时(功能(){socket.emit('登录', dataRet);},1000);

可以更改为:

 } else {var p = 行[0];var dataRet = new Player(p.id, p.nick, p.map_id, p.x, p.y, connexion, function () {socket.emit('登录', dataRet);}).toJson();控制台日志(dataRet);}

但在这里,正如我所说,没有什么是异步的,而且你的 dataRet 甚至在你运行 setTimeout 之前就已经设置好了,所以这并没有解决你的问题,但它正在回答你的问题.>

I am working on a browser-game in Node.Js and I have this script :

game.js >>

var config = require('./game_config.js');
var mysql = require('mysql');
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var connexion = mysql.createConnection({
    'host': config.DB_HOST,
    'user' : config.DB_USER,
    'password' : config.DB_PASS,
    'database' : config.DB_NAME 
});
var Player = require('./server/class.player.js');

io.on('connect', function(socket) {
    console.log('Co');
    var player
    socket.on('login', function(data) {
        connexion.query("SELECT * FROM player WHERE nick = '"+data.login+"' AND pass = '"+data.pass+"'", function(err, rows) {
            if (err) {
                throw err;
            } else {
                if (rows.length == 0) {
                    var dataRet = "LOG";
                    socket.emit('login', dataRet);
                } else {
                    var p = rows[0];
                    var dataRet = new Player(p.id, p.nick, p.map_id, p.x, p.y, connexion).toJson();
                    console.log(dataRet);
                }
                // Without setTimeout it wouldn't work because the object didn't have the time to instantiate
                setTimeout(function() {
                    socket.emit('login', dataRet);
                },1000);
            }
        });
    });
    socket.on('disconnect', function(socket) {
        console.log('Disco');
    });
});

class.Player.js >>

var Player = function (id, name, map_id, x, y, connexion) {
    this.id = id;
    this.name = name;
    this.map_id = map_id ;
    this.x = x;
    this.y = y;
    this.link = connexion;
    this.toJson = function () {
        return {
            'id' : this.id,
            'name' : this.name,
            'map_id' : this.map_id,
            'x' : this.x,
            'y' : this.y
        };
    }
}

module.exports = User;

So basicly, my code works fine thanks to the "setTimeout()" in game.js (for the socket.emit() event). If I don't use it, the object 'dataRet' doesn't have the time to instantiate due to the asynchronousity of Node.js, so the socket emits "undefined" or "null".

So I was thinking, there MUST be a way to listen for an object instantiation in order to emit it through socket.io as soon as it's done.

解决方案

Warning: SQL Injection Vulnerability

This is not related your question per se but this is quite important - you have a huge SQL injection vulnerability and anyone can do anything to your database.

Instead of:

connection.query(
  "SELECT * FROM player WHERE nick = '"
  + data.login + "' AND pass = '" + data.pass + "'",
  function (err, rows) {
    //...
  }
);

either use:

connection.escape(data.login) and connection.escape(data.pass) in place of data.login and data.pass

or:

connection.query(
  "SELECT * FROM player WHERE nick = ? AND pass = ?", [data.login, data.pass],
  function (err, rows) {
    // ...
  }
);

It is not only safer but also actually much easier to read and understand. See: Escaping query values in node-mysql manual.

The Answer

Now, back to your question. There is nothing asynchronous about your Player constructor so your problem must be something else. What is strange here us that your Player.js exports User (that is not defined) and not Player (that is defined) so I'm surprised it even works at all. Or you maybe posted a different code than what you're actually using which would explain why you have a race condition that is not obvious from the code.

But if your Player constructor was making some asynchronous calls then I would suggest adding a callback argument and calling it from the constructor:

var Player = function (id, name, map_id, x, y, connexion, callback) {
    this.id = id;
    this.name = name;
    this.map_id = map_id ;
    this.x = x;
    this.y = y;
    this.link = connexion;
    this.toJson = function () {
        return {
            'id' : this.id,
            'name' : this.name,
            'map_id' : this.map_id,
            'x' : this.x,
            'y' : this.y
        };
    }

    // some async call that you have to wait for
    // symbolized with setTimeout:
    setTimeout(function () {
      if (callback && typeof callback === 'function') {
        callback(this);
      }
    }, 1000);
}

and then you can pass a callback to your constructor, so this:

          } else {
                var p = rows[0];
                var dataRet = new Player(p.id, p.nick, p.map_id, p.x, p.y, connexion).toJson();
                console.log(dataRet);
            }
            // Without setTimeout it wouldn't work because the object didn't have the time to instantiate
            setTimeout(function() {
                socket.emit('login', dataRet);
            },1000);

could change to something like:

          } else {
                var p = rows[0];
                var dataRet = new Player(p.id, p.nick, p.map_id, p.x, p.y, connexion, function () {
                    socket.emit('login', dataRet);
                }).toJson();
                console.log(dataRet);
            }

but here, as I said, nothing is asynchronous and also your dataRet is already set even before you run the setTimeout so this is not solving your problem, but it is answering your question.

这篇关于是否可以在 Node.js 中监听对象实例化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

更多推荐

[db:关键词]

本文发布于:2023-03-31 23:05:03,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/815311.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:实例   对象   Node   js

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!