[英]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.