2017-07-14 50 views
0

我試圖使用npm包csv-parser來解析我的csv文件,並遇到事件發生順序的問題。使用csv解析器的同步發射事件

活動發射順序

  1. 「頭」:要插入瞭解CSV元數據到數據庫中,並返回一個ID值
  2. 「數據」:想用值從返回的ID頭事件的所有數據事件
  3. '數據'
  4. '數據'
  5. ...
  6. 結束

顯然,節點的異步性質意味着我在'headers'中緩慢的數據庫訪問在第一個'data'事件發出時沒有返回,因此我沒有csv的id。我能想到的唯一選擇是將所有數據行緩存到某個臨時變量中,然後在讀取完整個csv後再推送所有數據。考慮到我可能有非常大的csv文件,這似乎是一個壞主意?任何關於解決這個問題的更好方法的建議?

編輯:添加一些代碼(僞代碼,沒有實際測試過)

let headerList = null; 
let dataArray = []; 
fs.createReadStream(path) 
    .pipe(csv()) 
    // Parse the headers into a comma delimminated string 
    .on('headers', function(headers) { 
     // some parsing logic and then assigned to variable 
     headerList = headers; 
    }) 
    .on('data', function (data) { 
     // Some push of data into a variable 
     dataArray.push(data); 
    }) 
    .on('end', function() { 
     // create the base upload object 
     const id = uploads.createUpload(filename, headerList, new Date()); 

     // insert data 
     uploads.insertUploadData(id, dataArray); 
    }) 
+0

也許讀取第一行,只是爲了獲取元數據。進行數據庫調用。當第一次數據庫調用返回id時,則執行完整的解析過程......然後,您不必緩存任何內容。只要讀第一行兩次。 – joshp

+0

是的,這不是一個壞主意。沒有想到這樣做。 – Daniel

回答

1
  1. 當你拿到headers事件,unpipe()讀取流。這將使文件讀取器進入暫停狀態,因此您不必在內存中緩衝一堆內容。

  2. 由於數據是以塊(通常爲64 kB)的形式從磁盤中讀取的,因此CSV解析器仍然會發出data事件,因爲它會繼續解析當前塊。您仍然需要緩衝數組中的少量行。

  3. 當你從數據庫中需要的所有信息:

    1. 提交緩衝行到數據庫。

    2. 移除原始的data事件處理程序(排隊到數組的那個處理程序)並附加一個將行直接提交到數據庫的處理程序。

    3. pipe()將讀取流返回到CSV解析器。


您可能還需要考慮,如果你的程序從硬盤讀取並解析CSV速度比你的數據庫可以接受的數據會發生什麼。由於沒有背壓,大量的數據庫操作可能會在內存中排隊等候,直到用完爲止。

如果有很多待處理的數據庫操作,您應該暫停文件讀取流。

+0

有道理。沒有意識到你可以像這樣解開流。謝謝 – Daniel

+0

關於積壓的好處。考慮到它將在不同的服務器上,我想這種情況是完全可能的。 – Daniel