2015-08-04 34 views
7

Niestety, nie jestem nowy w węźle i mam pewne zamieszanie dotyczące asynchronicznego/synchronicznego wykonywania węzła.Węzeł + Sequelize: Jak sprawdzić, czy element istnieje przed dodaniem? (asynchroniczne zamieszanie)

Używam węzła, kontynuuj pracę z sqlite i async.js.

Mam serię Articles, z których każda ma numer Authors.

Dla każdego Authors w każdym Article, chciałbym sprawdzić, czy istnieje Author. Jeśli nie, utwórz go.

Problem polega na tym, że przy pierwszym uruchomieniu tworzony jest zduplikowany autor, zakładam ze względu na asynchroniczną funkcjonalność powodującą problem z sprawdzaniem istnienia.

Na przykład, przy tablicy: authors = ['A. Test', 'B. Test', 'C. Test', 'A. Test']

i kod:

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

Na pierwszym biegu, stworzy tabelę:

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

Co robię źle? Wygląda na to, że brakuje mi podstawowej koncepcji wykonania asynchronicznego vs synchronicznego w węźle.

(Próbowałem też async.eachSeries która ma wykonać szeregowo zamiast równolegle?)

EDIT: Lekko refactored, ale nadal tworzenie duplikatów

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

Odpowiedz

0

zmienić każdy do eachSeries i faktycznie zadzwoń na oddzwonienie i powinieneś być złoty.

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

Hm, to nie wydaje się działać, to dodanie tylko pierwszego autora. – waffl

+0

Czy Twój Author.create obsługuje wywołanie zwrotne, o którym wspomniałem w komentarzach? – trex005

+0

Przepraszam, jak masz na myśli? Metoda 'create' jest [implementowana przez sequelize] (http://docs.sequelizejs.com/en/latest/api/model/#createvalues-options-promiseinstance), co skutkuje obietnicą. – waffl

6

Author.count nie jest naprawdę potrzebne, chyba że potrzeba hrabia. Zobacz findOrCreate().

Z findOrCreate() możesz mieć następujące. (Red trex005 na snippet za to)

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) { 
 
     console.log('Author already exists'); 
 
     } 
 

 
     console.log('Created author...'); 
 
     callback(); 
 
    }); 
 
    }) 
 
})

+0

Cześć, dziękuję za odpowiedź, faktycznie wypróbowałem 'findOrCreate' (i odświeżono do nieco czystszego fragmentu dodanego do mojej odpowiedzi powyżej), ale 'findOrCreate' powodował różnego rodzaju problemy z blokowaniem sqlite/blokowaniem bazy danych - najwyraźniej działo się to również w postgresie dla niektórych użytkowników Niestety mój nowy fragment wciąż nie działa i nadal tworzy duplikaty. – waffl

+1

@ joshua-f btw, możesz użyć metody spread zamiast metody oddzielania argumentów obietnicy Przykład: '.spread (function (author, isCreated) {...});' –

+0

@AliBARIN Oh słodko, nie wiedziałem o tym –