詳解Node.js模塊間共享數(shù)據(jù)庫連接的方法
這個標(biāo)題本身就是一個命題,因為使用默認方式的情況下,一個 Node.js 應(yīng)用里的各個模塊都是共享的同一個數(shù)據(jù)庫連接。但是如果姿勢不對,可能會很丑陋,甚至可能會出錯。
你可以忽略下面這部分,直接切入正題。
背景
最近在做專業(yè)課程設(shè)計,題目是“機票預(yù)訂管理系統(tǒng)”。需求比較簡單,就試著拿最近在學(xué)的 Node.js 來做了。本來還在調(diào)研用何種 Node.js 框架比較合適,看了幾個框架之后發(fā)現(xiàn)這是殺雞用牛刀,有看文檔查資料的時間還不如直接動手寫了。最后寫完我會把代碼放到 Github 上,歡迎大家批評指正。
數(shù)據(jù)庫方面,以為我比較熟悉和喜歡 JSON (SQL 沒學(xué)好就承認唄-_-#),所以就選擇了 MongoDB。Node + Mongo 是近幾年越來越熱門的后端組合,網(wǎng)上有很多關(guān)于如何一起使用的資料。但為了節(jié)約時間(課程設(shè)計也就一個多星期),把精力多集中在系統(tǒng)和邏輯上,我用了 Mongoose 這個專門用于 MongoDB 數(shù)據(jù)建模的 Node.js 擴展,用它來大大減少操作數(shù)據(jù)庫的代碼。
正題
我建立了兩個數(shù)據(jù)模型(Model),一個是用戶(User),一個是航班(Flight),分別封裝到了 user.js, flight.js 這兩個模塊(Module)里面。Model 專門負責(zé)和數(shù)據(jù)庫交互,用戶和航班這兩個模塊都需要連接數(shù)據(jù)庫,一開始我的代碼是這樣的:
// ----- user.js ----- // require mongoose.js 引用mongoose.js var M = require('mongoose'); // connect to database 連接數(shù)據(jù)庫 M.connect('mongodb://localhost/test'); // ... some other code ... // ----- flight.js ----- // require mongoose.js 引用mongoose.js var M = require('mongoose'); // connect to database 連接數(shù)據(jù)庫 M.connect('mongodb://localhost/test'); // ... some other code ... // ----- models.js ----- var user = require('./user'), flight = require('./flight'); // ----- index.js ----- var Models = require('./models');
且不說這種寫法一點都不 DRY,這種方式本身就是錯誤的。當(dāng)我運行 index.js 時,會出現(xiàn)如下錯誤。
> node index.js > Connection error: { [Error: Trying to open unclosed connection.] state: 2 }
錯誤是:嘗試打開未關(guān)閉的連接。
所以我們應(yīng)該在一個地方連接一次數(shù)據(jù)庫,然后其他需要連接數(shù)據(jù)庫的模塊通過這個模塊來和數(shù)據(jù)庫交互。就好像插線板,義無反顧地吼叫道:“墻上就一個插座,你們不要搶了!放著我來!你們。。。就可以了!”
具體方案
我們把連接數(shù)據(jù)庫的動作放到一個模塊里,并且把連接暴露給整個應(yīng)用中的其他模塊,然后其他需要連接數(shù)據(jù)庫的模塊引用這個連接即可。
// ----- database.js ----- var M = require('mongoose'); M.connect('mongodb://localhost/test'); // reference to the database connection 為這個連接創(chuàng)建一個引用 var db = M.connection; // expose to modules that require database.js 把這個引用暴露給引用 database 模塊的其他模塊 module.exports = db; // ----- user.js ----- flight.js 類似 ----- // ... some other code ... // 我們會在 models.js 中,把數(shù)據(jù)庫連接的引用作為參數(shù)傳進來 module.exports = function( db ){ if( db ){ // ... do things with the connection ... 如果連接了數(shù)據(jù)庫,就可以執(zhí)行數(shù)據(jù)庫相關(guān)的操作了 } } // ----- models.js ----- // require database module, retrieve the reference to database connection 引用 databse 模塊,獲取數(shù)據(jù)庫連接的引用 var db = require('./database'); // 把數(shù)據(jù)庫連接的引用傳入需要連接數(shù)據(jù)庫的模塊,任務(wù)完成! var user = require('./user')( db ), flight = require('./flight')( db );
這就是讓一個 Node.js 應(yīng)用的多個模塊共享數(shù)據(jù)庫連接的一種方法。是我在 StackOverflow 上面看到的。如果你有更好的方法,歡迎在評論中分享給大家!
相關(guān)文章
JavaScript中Number.NEGATIVE_INFINITY值的使用詳解
這篇文章主要介紹了JavaScript中Number.NEGATIVE_INFINITY值的使用,是JS入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下2015-06-06Javascript & DHTML 實例編程(教程)基礎(chǔ)知識
Javascript & DHTML 實例編程(教程)基礎(chǔ)知識...2007-06-06ECMAScript5(ES5)中bind方法使用小結(jié)
這篇文章主要介紹了ECMAScript5(ES5)中bind方法使用小結(jié),bind和call以及apply一樣,都是可以改變上下文的this指向的,需要的朋友可以參考下2015-05-05微信公眾號開發(fā) 自定義菜單跳轉(zhuǎn)頁面并獲取用戶信息實例詳解
這篇文章主要介紹了微信公眾號開發(fā) 自定義菜單跳轉(zhuǎn)頁面并獲取用戶信息實例詳解的相關(guān)資料,需要的朋友可以參考下2016-12-12script標(biāo)簽屬性用type還是language
本文介紹了javascript腳本中標(biāo)簽屬性type與language的區(qū)別分析,有需要的小伙伴可以參考下2015-01-01