我使用Ember-Data和[Kurko的Ember Data IndexedDB适配器](https://github.com/kurko/ember-indexeddb-adapter)与多个hasMany关系使用Ember.js。我能够成功添加hasMany关系而没有任何问题。我的问题在于删除hasMany关系。
App.Race = DS.Model.extend({
name: DS.attr('string'),
...
athletes: DS.hasMany('athlete', {async: true}),
...
});
App.Athlete = DS.Model.extend({
bib: DS.attr('number'),
name: DS.attr('string'),
...
splits: DS.hasMany('split', {async: true}),
races: DS.hasMany('race', {async: true}),
...
});
App.Split = DS.Model.extend({
distance: DS.attr('string'),
time: DS.attr('string'),
athlete: DS.belongsTo('athlete', {async:true}),
race: DS.belongsTo('race', {async: true}),
...
});
在删除运动员时,有时会从指定的athlete
模型中删除race
引用,从而导致应用程序中断。始终会删除athlete
模型,并始终删除所有必需的splits
模型。我知道它与我的存储的异步性质有关,但我无法在行动中找出问题:
removeAthlete: function() {
var self = this,
athlete = this.get('model');
// Get race from athlete
athlete.get('races').then(function(races){
// Remove athlete from races
races = races.toArray();
races.forEach(function(race){
console.log('removing athlete from race');
race.get('athletes').removeObject(athlete);
race.save();
});
// destroy splits
athlete.get('splits').then(function(splits) {
console.log('retrieved splits');
splits.toArray().forEach(function(split) {
console.log('removing split');
split.destroyRecord();
});
// destroy athlete
athlete.destroyRecord();
});
});
},
...
经过一些通知尝试后,我意识到该错误与从竞赛中删除athlete
引用有关。随着我的进步,我会给予更多更新。
答案 0 :(得分:1)
在为这个问题研究JSBin时,我能够弄清楚问题是什么以及如何解决它。希望我能说出来。问题在于我对存储的异步调用的嵌套(或缺乏)。
在removeAthlete
方法中,我没有将异步调用嵌套到我的存储容器中,这导致athlete.destroyRecord()
被过早调用。
removeAthlete: function() {
var self = this,
athlete = this.get('model');
athlete.get('races').then(function(races){ // Get race from athlete
races = races.toArray();
races.forEach(function(race){ // Remove athlete from each race
race.get('athletes').removeObject(athlete);
race.save();
});
// async call to splits
athlete.get('splits').then(function(splits) {
// destroy each split
splits.toArray().forEach(function(split) {
split.destroyRecord();
});
/*
call to destroy athlete is called while other async calls are
waiting to get responses
*/
athlete.destroyRecord();
});
});
},
异步调用在等待响应时继续执行代码,因此在收到异步响应之前调用每个异步调用之后的代码。根据{{1}}数组中的拆分数量,可以在执行前一行中的代码之前调用splits
。如果athlete.destroyRecord
较少,则splits
会尽快被调用。如果还有更多,则稍后调用athlete.destroyRecord
,之后调用所有前面的行。所以我的解决方案是:
athlete.destroyRecord
通过这种方式,依次调用依赖于其他异步调用结果的每个异步调用。仅在removeAthlete: function() {
var self = this,
athlete = this.get('model');
// Get race from athlete
athlete.get('races').then(function(races){
// Remove athlete from races
races = races.toArray();
races.forEach(function(race){
race.get('athletes').removeObject(athlete);
race.save().then(function(){
if(races.indexOf(race) === races.get('length') -1) {
athlete.get('splits').then(function(splits) {
splits.toArray().forEach(function(split) {
split.destroyRecord();
});
// destroy athlete
athlete.destroyRecord();
});
}
});
});
});
},
移除所有splits
后才会删除athletes
。我希望找到一个更简单,更有效的解决方案。这似乎不是最好的方法。所以我不会将此标记为正确的答案。希望其他人知道更好的方法。