web-dev-qa-db-fra.com

Node + Sequelize: comment vérifier si un élément existe avant l'ajout? (Confusion asynchrone)

Je suis malheureusement nouveau sur le nœud et je rencontre une certaine confusion concernant l'exécution asynchrone/synchrone du nœud.

J'utilise nœud, séquencer avec sqlite et async.js.

J'ai une série de Articles, chacune ayant un certain nombre de Authors.

Pour chaque Authors dans chaque Article, je voudrais vérifier si le Author existe. Sinon, créez-le.

Le problème est que lors de l'exécution initiale, des auteurs en double sont créés, je suppose en raison de la fonctionnalité asynchrone provoquant un problème de vérification de l'existence.

Par exemple, avec le tableau: authors = ['A. Test', 'B. Test', 'C. Test', 'A. Test']

et le 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()
          })
        }
      })
    })
  })

Lors de la première exécution, créera une table:

ID | name
------------
0  | A. Test
1  | B. Test
2  | C. Test
3  | A. Test

Qu'est-ce que je fais mal? Il me semble manquer un concept fondamental de l'exécution asynchrone vs synchrone dans Node.

(J'ai également essayé async.eachSeries qui est censé s'exécuter en série plutôt qu'en parallèle?)

Edit: légèrement refactorisé, mais créant toujours des doublons

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()
        })
      }
    })
  })
20
waffl

Author.count N'est pas vraiment nécessaire, sauf si vous avez besoin du nombre. Voir findOrCreate () .

Avec findOrCreate(), vous pourriez avoir les éléments suivants. (Extrait de trex005 modifié pour cela)

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();
    });
  })
})
18
Joshua F

Remplacez chacun par eachSeries et appelez le rappel et vous devriez être en or.

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();
          })
        }
      })
    })
  })
0
trex005