[英]Variable passing in Node.js?
因此,我正在尝试将我的聊天系统升级到Node.js,而且多年来我一直没有这种感觉!
在PHP中,它效率低下,但绝对有道理。 请求启动,它找出用户信息,房间信息,解析消息等。 相当线性。 它在不同的地方调用了几个函数,但是每次都只需要直接向该函数发送所需的信息即可。 完成该功能后,它将返回,然后使用其他信息使用其他信息完成更多工作。 如果存在异常,通常会在可以向用户发出警报的级别捕获异常。
据我了解,Node.js绝对不能像这样工作,而是主要由回调提供支持-而且我正在进行很多回调。 它必须处理初始连接,然后必须检查cookie文件是否存在,然后必须读取cookie文件,然后必须从数据库中获取一些用户信息,然后必须获取一些用户信息。数据库中的其他用户信息,然后它必须从数据库中获取更多用户信息,然后它必须将用户添加到房间中,如果一段时间没有人在场,则必须获取该用户来自数据库的房间信息,然后最终响应该请求。 完成后,至少还会有两个级别用于权限检查。
它与PHP流程没有太大不同,但是在PHP中它是通过Apache多线程的,因此请求可以放在那儿,等待DB调用完全返回。 用户查找,会议室订阅,权限均单独处理。
在Node.js的,系统的“当你做完这些”不太难绕到我的头(我使用的客户端JS和jQuery很多),但变量传递肯定是。 其中很大的一部分是try / catch被回调打败了。 如果房间数据查找查询失败,则该函数需要知道应将错误发送回哪个连接(到那时可能是过去的两个或三个连接),因为它不会冒充回溯到多个级别。 因此,在此过程中,需要通过每个回调直接传递该连接对象。 在处理异常时,这只是轻微的令人作呕,因为异常可能在任何地方发生,但是当您到达必须将其他变量一直传递到最后一个回调的行的地步时,我的手指拒绝进一步键入直到我研究出如此严重的错误!
因此,我想我想知道的是,是否存在我不熟悉的任何“ hack”,可能会导致变量“跳过”非嵌套的回调。 无限期地尝试/捕获链也是很不错的。
编辑:我在琐碎数百行代码时遇到了麻烦,所以让我们看看我是否可以通过回调堆栈提供一些视觉帮助。 同一行上的任何内容都是直接调用,下一行是回调。
connection.on('messaage') -> controller.validateUser -> fs.exists
fs.readFile
function() -> controller.addUser -> factory.user -> user.refreshData -> db.query
user.refreshChars -> db.query
user.refreshBlocks -> db.query
function() -> controller.addRoom -> factory.room -> room.refreshData -> db.query
room.getRole -> db.query
function() -> room.getUserList -> connection.sendUTF
如您所见,这些函数大多位于对象中,而不仅仅是嵌套的未命名函数,因为它们通常需要以任意顺序从多个位置进行访问。 问题是,某些级别需要用户对象,而有些则不需要。 如果try / catch正常工作,则仅第一个和最后一个需要知道连接才能将信息发送回去。
我需要的是一种为这些不同功能提供不同信息的方法,而不必在每个功能之前都添加不需要的功能。 这是不受欢迎的做法。 我还需要各种用户对象函数以非常不同的方式失败-该对象不需要关心自身的方式,因为这是调用函数的责任。
initial(); // begins the process
// this starts things off
function initial() {
var props = { // this is the common object
onerror: function(err) {
if (err.msg === "reallyBadError")
return false; // false means stop
else
return true; // true means we can continue
},
someInitialData: {whatever:"data"}
};
doSomethingAsync(getFirstCallback(props));
}
function getFirstCallback(props) {
// return the actual callback function
return function(err, info) {
// if callback was passed an error, handle it
if (err && props.onerror(err) === false)
return;
props.info = info; // add something to props
doAnotherAsync(getSecondCallack(props));
};
}
function getSecondCallback(props) {
// return the actual callback function
return function(err, foo) {
// if callback was passed an error, handle it
if (err && props.onerror(err) === false)
return;
// maybe do something with props.info
props.foo = foo; // add something to props
doOneMoreAsync(getFinalCallack(props));
};
}
function getFinalCallback(props) {
// return the actual callback function
return function(err, bar) {
// if callback was passed an error, handle it
if (err && props.onerror(err) === false)
return;
// maybe do something with props.info and props.foo
// we also have access to the original props.whatever
};
}
这是一个原型版本:
var r = new Requester(); // begins the process
// Here's the implementation
function Requester() {
// "this" is the common object
this.someInitialData = {whatever:"data"};
doSomethingAsync(this.firstCallback.bind(this));
}
Requester.prototype.onerror: function(err) {
if (err.msg === "reallyBadError")
return false; // false means stop
else
return true; // true means we can continue
};
Requester.prototype.firstCallback = function(err, info) {
// if callback was passed an error, handle it
if (err && this.onerror(err) === false)
return;
this.info = info;
doAnotherAsync(this.secondCallack.bind(this));
};
Requester.prototype.secondCallback = function(err, foo) {
// if callback was passed an error, handle it
if (err && this.onerror(err) === false)
return;
this.foo = foo;
doOneMoreAsync(this.finalCallack.bind(this));
};
Requester.prototype.finalCallback = function(err, bar) {
// if callback was passed an error, handle it
if (err && this.onerror(err) === false)
return;
// The final code
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.