也许我不完全理解承诺或Sequalize,但经过一段时间的努力,感觉异步数据库操作仅适用于更简单的情况。 并且通过询问同步数据库访问的问题数量,它看起来我不是唯一的。
这是我的情况。假设我们有含有化合物的CSV文件,其中每行包含有关化合物的信息,以及以分号分隔的成分列表。我们希望从中填充成分表,但没有重复。
例如,如果文件包含行
C1 IngA; IngB
C2 IngA; IngC
我们想要有三个记录的成分表,IngA,IngB和IngC。 因此,当读取行时,它应该保存化合物,对于每个成分检查是否已经存在,如果不存在则添加它。这是代码:
var lineReader=require('readline').createInterface({
input: require('fs').createReadStream(filename)
});
lineReader.on('line', function(line) {
let parts=line.split('\t');
compoundModel.create({
name: parts[0],
}).then(entity => {
let ingredients=parts[1].split(';');
ingredients.forEach((ing, index) => {
ingModel.findOne({
where: {name: ing}
}).then(ingEntity => {
if (ingEntity) {
return ingEntity;
}
return ingModel.create({
name: ing
})
});
}).then(ingEntity => {
//something else
});
});
});
问题是IngA被插入表中两次。我的猜测是,查找或创建Sequelize方法会返回promises,并且从文件中读取行的数据更快。因此,当读取新行并尝试找到IngA时,尚未插入第一行的IngA。
我尝试过几种方法,但对于这类任务来说,一切似乎都太复杂了。更重要的是,不起作用。
答案 0 :(得分:1)
答案 1 :(得分:1)
请在解决方案之下,它应该有效。
var await = require('asyncawait/await');
var lineReader=require('readline').createInterface({
input: require('fs').createReadStream(filename)
});
lineReader.on('line', function(line) {
let parts=line.split('\t');
compoundModel.create({
name: parts[0],
}).then(entity => {
let ingredients=parts[1].split(';');
ingredients.forEach((ing, index) => {
await(ingModel.findOrCreate({
where: {name: ing}, defaults: {name: ing},
}).spread(function(_record, _created){
//Do something if required. _create will return true in case of entry already exists
}))
}).then(ingEntity => {
//something else
});
});
});
在执行此操作前npm install asyncawait
。在await
的帮助下,它会等到承诺在执行下一个承诺之前完成它的执行。