2016-10-04 10 views
0

私はSequlizeでユーザーとファイルのモデルを持っています。ユーザーは複数のファイルを持つことができます。 私はアソシエーションを持っています db.User.hasMany(db.File、{as: 'Files'、foreignKey: 'userId'、constraints:false});Sequelize(Node js)でオブジェクトを関連付ける方法は?

複数のファイルを持つユーザーオブジェクトを初期化して、データベースに保存します。

私は次のコードを書いた:

var files = []; 

     var file1 = models.File.build(); 
     file1.name = "JPEG"; 

     file1.save().then(function() { 

     }); 

     files.push(file1); 

     var file2 = models.File.build(); 
     file2.name = "PNG"; 

     file2.save().then(function() { 

     }); 

     files.push(file2); 


var newUser = models.User.build(); 
     newUser.email = email; 
newUser.save().then(function (usr) { 

files.forEach(function (item) { 
    newUser.addFile(item); 
}); 

}); 

をしかし、私は時々、いくつかのファイルがユーザーに関連付けられていなかった、バグを発見しました。

これらのファイルの外部キーを設定するための(nodejsログの)コマンド(更新)が見つかりました。 しかし、コマンドは実行されませんでした。いくつかのファイルの外部キー(userId)は空でした。

私は問題が非同期クエリにあると思います。 このバグを回避するコード構造を整理するにはどうすればよいですか?

+0

かかわらず、このためにcoと呼ばれる小さなノードモジュールを使用する必要が

だからあなたのような何かを行うことができますユーザーの後にファイルを作成し、ユーザーIDをfileの定義に追加しますか? – oriaj

答えて

0

問題はまさにそれが非同期コードだと思います。

コールバックの内部で関数を移動する必要があります。そうしないと、ファイルが作成される前にコードが実行されます。

JavaScriptは次の行に移動する前に待機しないため、JavaScriptは次の行が完了したかどうかに関係なく実行されます。移動する前に待つ感覚はありません。

基本的には、移動する前にファイルが保存されるのを待たずに、まだ存在しないものを追加しています。

これはちょうどthenコールバックの内側にコードを移動、しかし働くだろう:

var files = []; 

var file1 = models.File.build(); 
file1.name = "JPEG"; 

file1.save().then(function() { 
    files.push(file1); 

    var file2 = models.File.build(); 
    file2.name = "PNG"; 

    file2.save().then(function() { 
     files.push(file2); 

     var newUser = models.User.build(); 
     newUser.email = email; 
     newUser.save().then(function (usr) { 
      files.forEach(function (item) { 
       newUser.addFile(item); 
      }); 
     }); 
    }); 
}); 

しかし、それは厄介です。代わりに、あなたはこのような連鎖約束することができます:

var files = []; 

var file1 = models.File.build(); 
file1.name = "JPEG"; 

file1.save() 
    .then(function(file1) { 
     files.push(file1); 

     var file2 = models.File.build(); 
     file2.name = "PNG"; 

     return file2.save(); 
    }) 
    .then(function(file2) { 
     files.push(file2); 

     var newUser = models.User.build(); 
     newUser.email = email; 

     return newUser.save(); 
    }) 
    .then(function(newUser) { 
     files.forEach(function(item) { 
      newUser.addFile(item); 
     }); 
    }); 

は、今では少しクリーナーが、まだ少し厄介とも少し混乱です。したがって、次のようにジェネレータ関数を使用することができます。

var co = require('co'); 

co(function*() { 
    var files = []; 

    var file1 = models.File.build(); 
    file1.name = "JPEG"; 

    yield file1.save(); 
    files.push(file1); 

    var file2 = models.File.build(); 
    file2.name = "PNG"; 

    yield file2.save(); 
    files.push(file2); 

    var newUser = models.User.build(); 
    newUser.email = email; 
    newUser.save(); 

    files.forEach(function(item) { 
     newUser.addFile(item); 
    }); 
}); 

これではるかに優れています。

緊密に見て、あなたは何が起こっているかを見ます。 coは、基本的にアスタリスクがアスタリスクの*のジェネレータ関数を受け入れます。これは、yield式のサポートを追加する特別な関数です。

yield式は基本的に、移動前にthen()コールバックが呼び出されるのを待っており、thenコールバックに引数がある場合、それも返します。

var gif = yield models.File.create({ 
    name: 'gif' 
}); 

の代わり:

models.File.create({ 
    name: 'gif' 
}).then(function(gif) { 

}); 

あなたが「ドン理由だけnpm install --save co

関連する問題