2016-10-04 49 views
0

我在Sequize中擁有User和File模型。用戶可以有幾個文件。 我有關聯 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

爲什麼你不」在用戶之後創建文件並在文件的定義中添加用戶標識? – oriaj

回答

0

問題正是你認爲它是異步代碼。

您需要移動回調中的函數,否則代碼將在創建文件之前運行。

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) { 

}); 

你必須使用一個名爲co小節點模塊這雖然只是npm install --save co

相關問題