2016-04-28 42 views
0

我正在Node中編寫一個獨立的Web刮板,從命令行運行,它在一組頁面上查找特定數據,提取頁面視圖數據來自Google Analytics並將其全部保存在MySQL數據庫中。幾乎所有的東西都準備好了,但今天我發現了一個問題,就是我在數據庫中寫入數據的方式。Node.js設計:使用函數寫入數據庫的多個異步函數作爲閉包傳遞

爲了使事情更容易讓我們假設我有一個index.js文件和兩個控制器 - dbwebDb讀取/寫入數據到db,web使用可配置數量的PhantomJs實例對頁面進行剪貼。

的Web公開了一個功能checkTargetUrls(urls, writer) 其中urls與網址數組進行檢查和writer是一個可選參數,僅稱爲如果它是一個功能,並有要被寫入的數據。

現在我通過作家的方式顯然是錯誤的,但看起來如下(index.js):

some code here 
.... 
let pageId = 0; 
... some promises code, 
which checks validy of urls, 
creates new execution in the database, etc. 
... 

.then(ulrs => { 
    return web.checkTargetUrls(urls, 

     function(singleUrl, pageData) { 
     ... 
     a chain of promisable functions from db controller, 
     which first lookup page id in the db, then its 
     puts in the pageId variable and continues with write to db 
     ... 

}).then(() => { 

logger.info('All done captain!'); 
}).catch(err => {logger.error(err}) 

在隨機pageId得到由前述的ID覆蓋效果/後頁的和無效的數據被保存。在web裏面,有多達10個PhantomJs併發實例正在運行,它們在分析頁面後調用writer函數。請原諒我的語言,但對我來說,如果我有一個對象的10個實例,然後依賴寫在單例中,導致覆蓋問題(不知道如何正確用JS/Node.js表示)。

到目前爲止,我已經找到了解決這個問題的一個方法,但是它引入了緊密耦合,這很醜陋。如果我把writer代碼放在一個單獨的模塊中,然後直接從web控制器中加載它,那麼所有的工作都很好。但對我而言,這是一種糟糕的設計模式,寧願不要這樣做。

var writer = require('./writer'); 

function checkTargetUrls(urls, executionId) { 

return new Promise(
    function(resolve, reject) { 

     let poolSize = config.phantomJs.concurrentInstances; 
     let running = 0; 

     .... 
     a bit of code goes here 
     .... 
     if (slots != undefined && slots != null && slots.data.length > 0) { 

      return writer.write(executionId, singleUrl, slots); 
     } 
     ... 
     more code follows 
}) 
} 

我也很難findng一個更好的解決方案,在那裏我仍然可以通過writercheckTargetUrls(urls, writer)函數的參數。任何人都可以指向正確的方向或建議在哪裏尋找答案?

回答

0

圍繞全局pageId的確切問題對我來說並不完全清楚,但是您可以通過從'web'控制器公開setWriter函數來減少耦合。

var writer; 
module.exports.setWriter = function(_writer) { writer = _writer }; 

然後靠近你index.js的頂部,是這樣的:

var web = require('./web'); 
web.setWriter(require('./writer')); 
+0

是的,我可以這樣做,但洗澡有助於解決問題更好;-) 的事情是pageId沒有適當的作用域,並被放置在代碼的一部分,這是作爲'單線程'執行的。將它移動到「作家」函數體內解決了覆蓋問題。 – Farrkhar