2017-03-08 69 views
0

我使用Sequelize將CSV文件中的數據導入到Nodejs系統中,但我在嘗試檢查之前是否插入了前一行時出現問題。在每次插入後遞歸提交

這是代碼我使用

exports.insertEmployee = function (employee) { 
    return new Promise((fulfill, reject) => { 
     models.Employee.create(employee) 
     .then(employee => fulfill(employee.dataValues)) 
     .catch(reject); 
    }); 
}; 

exports.importEmployee = function (employee) { 
    return new Promise((fulfill, reject) => { 
     models.Employee.findOne({where: {customID: employee.customID}, raw: true}).then(emp => { 
      if(emp) { 
       fulfill(emp); 
      } 
      else { 
       exports.insertEmployee(employee).then(fulfill); 
      } 
     }); 
    }); 
}; 

功能importEmployee將被調用多次行有像這樣

lines.forEach(line => { 
    let emp = line.employee; 
    importEmployee(emp).then(employee => {console.dir(employee)}); 
}); 

的問題,我具有CSV是當我檢查是否已經插入了具有相同customID的用戶時,數據庫尚未提交insert,因此它將始終返回false,並且我將使用相同的customID複製員工

我該如何解決這個問題?我嘗試使用交易,但也許我做錯了,因爲它不會幫助。

謝謝!

回答

1

它沒有工作,因爲你想在forEach裏執行一系列異步操作。這樣所有的記錄都會被插入,因爲執行檢查和插入的操作是同時運行的。爲了避免這種情況,您可以使用Bluebird模塊的mapSeries() Promise功能。它內置於續集中,因此不需要安裝額外的軟件包。

此外,您可以通過稱爲findOrCreate()的單個操作來執行檢查和插入操作,該操作返回一個實例和布爾值,用於定義此實例是創建還是簡單地作爲現有實例返回。

在合併這兩個功能,你的操作變得非常簡單和直接

// here is the function performing findOrCreate 
exports.createEmployee = function(employee) { 
    return models.Employee.findOrCreate({ 
     where: { customID: employee.customID }, 
     defaults: employee 
    }); 
}; 

更重要的是,你不必創建嵌套承諾,就像你在insertEmployeeimportEmployee一樣。大多數後續函數已經返回promise,所以你可以直接返回函數調用本身。

現在您可以遍歷lines並調用createEmployee方法。

models.sequelize.Promise.mapSeries(lines, (employee) => { 
    return createEmployee(employee); 
}).then(result => { 
    console.log(result); 
    // example output: [ [ Instance, true ], [ Instance, true ], [ Instance, false ] ] 
}); 

布爾true意味着實例被創建,而false意味着,例如從表,因爲這樣的記錄已經存在返回。