问题
I am unfortunately new to node and running into some confusion regarding the asynchronous/synchronous execution of node.
I am using node, sequelize with sqlite and async.js.
I have a series of Articles
, each of which has a number of Authors
.
For each Authors
in each Article
, I'd like to check if the Author
exists. If not, create it.
The problem is, on the initial run, duplicate authors are being created, I assume due to asynchronous functionality causing an issue with checking for existence.
For example, with the array: authors = ['A. Test', 'B. Test', 'C. Test', 'A. Test']
and the code:
async.each(authors, function(item, callback){
Author.sync().then(function(){
Author.count({ where: {name: item.trim()} }).then(function(count){
if (count != 0) {
console.log('Author already exists')
} else {
console.log('Creating author...')
Author.create({
name: item.trim()
})
}
})
})
})
On the first run, will create a table:
ID | name
------------
0 | A. Test
1 | B. Test
2 | C. Test
3 | A. Test
What am I doing wrong? I seem to be missing a fundamental concept of asynchronous vs synchronous execution in Node.
(I've also tried async.eachSeries which is supposed to execute in series rather than in parallel?)
Edit: Slightly refactored, but still creating duplicates
async.eachSeries(authors, function(authorName, callback){
Author.findOne({ where: {name: authorName.trim()} }).
then(function(author){
if (author) {
// Author exists...
callback()
} else {
// Author does not exist...
Author.create({
name: authorName.trim()
}).then(function(author){
callback()
})
}
})
})
回答1:
Author.count
isn't really needed, unless you need the count. See findOrCreate().
With findOrCreate()
you could have the following. (Edited trex005's snippet for this)
async.eachSeries(authors, function(item, callback) {
Author.sync().then(function() {
Author.findOrCreate({
where: {
name: item.trim()
},
defaults: { // set the default properties if it doesn't exist
name: item.trim()
}
}).then(function(result) {
var author = result[0], // the instance of the author
created = result[1]; // boolean stating if it was created or not
if (!created) { // false if author already exists and was not created.
console.log('Author already exists');
}
console.log('Created author...');
callback();
});
})
})
回答2:
Change your each to eachSeries
and actually call the callback and you should be golden.
async.eachSeries(authors, function(item, callback){
Author.sync().then(function(){
Author.count({ where: {name: item.trim()} }).then(function(count){
if (count != 0) {
console.log('Author already exists')
callback(); //assuming you want it to keep looping, if not use callback(new Error("Author already exists"))
} else {
console.log('Creating author...')
Author.create({
name: item.trim()
}).then(function(author){
callback();
})
}
})
})
})
来源:https://stackoverflow.com/questions/31815076/node-sequelize-how-to-check-if-item-exists-before-adding-async-confusion