我正在Node中編寫一個獨立的Web刮板,從命令行運行,它在一組頁面上查找特定數據,提取頁面視圖數據來自Google Analytics並將其全部保存在MySQL數據庫中。幾乎所有的東西都準備好了,但今天我發現了一個問題,就是我在數據庫中寫入數據的方式。Node.js設計:使用函數寫入數據庫的多個異步函數作爲閉包傳遞
爲了使事情更容易讓我們假設我有一個index.js
文件和兩個控制器 - db
和web
。 Db
讀取/寫入數據到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一個更好的解決方案,在那裏我仍然可以通過writer
爲checkTargetUrls(urls, writer)
函數的參數。任何人都可以指向正確的方向或建議在哪裏尋找答案?
是的,我可以這樣做,但洗澡有助於解決問題更好;-) 的事情是pageId沒有適當的作用域,並被放置在代碼的一部分,這是作爲'單線程'執行的。將它移動到「作家」函數體內解決了覆蓋問題。 – Farrkhar