如何处理Marionette中的异步请求?
How to deal with async requests in Marionette?
我正在尝试使用 2 API 请求的组合结果填充 Marionette 中的 ItemView。
this.standings = App.request('collection:currentStandings');
this.userInfo = App.request('model:userInfo');
this.standings.each(function(s) {
if (s.currentUser) {
s.set('alias', this.userInfo.alias);
s.set('imageURL', this.userInfo.imageURL);
}
});
userInfoView = new LeagueBar.UserInfo({ collection: this.standings });
问题是,组合从来没有发生过,因为在我尝试组合它们之前请求还没有完成。
我知道我可能需要为每个请求添加一个承诺,但我一直无法找到一种干净的方法来做到这一点。我可以做出 'collection:currentStandings' 和 'model:userInfo' return 承诺,但是,它们目前在代码的许多其他部分中使用,所以我必须返回并添加 .then()s 和.done() 遍及之前不需要的代码库。
有什么想法或建议吗?
编辑:
我目前以不太理想的方式解决了这个问题:我为别名创建了一个 template/view,为 imageURL 创建了一个 template/view,并保留了 template/view 作为排名信息。这似乎不是最好的方法,我很想知道解决这个问题的正确方法。
这是我要合并的两个请求:
Models.CurrentStandings = App.Collection.extend({
model: Models.PlayerStandings,
url: function() { return 'leagues/' + App.state.currentLeague + '/standings'; },
parse: function(standings) {
return _.map(standings, function(s) {
if (s.memberId == App.user.id)
s.currentUser = true;
return s;
});
}
});
App.reqres.setHandler('collection:currentStandings', function() {
weekStandings = new Models.CurrentStandings();
weekStandings.fetch({ success: function(data){ console.log(data); }});
return weekStandings;
});
Models.UserInfo = App.Model.extend({
url: 'users/me'
});
App.reqres.setHandler('model:userInfo', function(options) {
myuser = new Models.UserInfo();
myuser.fetch(options);
return myuser;
});
根据您的视图之间的依赖关系,有2种方案可供选择:
- 您可以创建处理 Models.UserInfo 的 'change' 事件的视图,并在数据准备就绪时(引发 Change/Reset 事件)重新呈现内容。这可能是您的解决方案。
如果您正在寻找一个在 Models.CurrentStanding 和 Models.UserInfo 都准备就绪之前不应创建 LeageBar.UserInfo 实例的解决方案,您 必须 return fetch 函数的结果,因此您可以从 setHandlers 中删除调用 fetch 并按如下方式使用它们:
this.standings = App.request('collection:currentStandings');
this.userInfo = App.request('model:userInfo');
var that=this;
that.standings.fetch().done(function(){
that.userInfo.fetch().done(function(){
that.standings.each(function(s) {
if (s.currentUser) {
//....
}
});
userInfoView = new LeagueBar.UserInfo({ collection: that.standings });
});
我正在尝试使用 2 API 请求的组合结果填充 Marionette 中的 ItemView。
this.standings = App.request('collection:currentStandings');
this.userInfo = App.request('model:userInfo');
this.standings.each(function(s) {
if (s.currentUser) {
s.set('alias', this.userInfo.alias);
s.set('imageURL', this.userInfo.imageURL);
}
});
userInfoView = new LeagueBar.UserInfo({ collection: this.standings });
问题是,组合从来没有发生过,因为在我尝试组合它们之前请求还没有完成。
我知道我可能需要为每个请求添加一个承诺,但我一直无法找到一种干净的方法来做到这一点。我可以做出 'collection:currentStandings' 和 'model:userInfo' return 承诺,但是,它们目前在代码的许多其他部分中使用,所以我必须返回并添加 .then()s 和.done() 遍及之前不需要的代码库。
有什么想法或建议吗?
编辑:
我目前以不太理想的方式解决了这个问题:我为别名创建了一个 template/view,为 imageURL 创建了一个 template/view,并保留了 template/view 作为排名信息。这似乎不是最好的方法,我很想知道解决这个问题的正确方法。
这是我要合并的两个请求:
Models.CurrentStandings = App.Collection.extend({
model: Models.PlayerStandings,
url: function() { return 'leagues/' + App.state.currentLeague + '/standings'; },
parse: function(standings) {
return _.map(standings, function(s) {
if (s.memberId == App.user.id)
s.currentUser = true;
return s;
});
}
});
App.reqres.setHandler('collection:currentStandings', function() {
weekStandings = new Models.CurrentStandings();
weekStandings.fetch({ success: function(data){ console.log(data); }});
return weekStandings;
});
Models.UserInfo = App.Model.extend({
url: 'users/me'
});
App.reqres.setHandler('model:userInfo', function(options) {
myuser = new Models.UserInfo();
myuser.fetch(options);
return myuser;
});
根据您的视图之间的依赖关系,有2种方案可供选择:
- 您可以创建处理 Models.UserInfo 的 'change' 事件的视图,并在数据准备就绪时(引发 Change/Reset 事件)重新呈现内容。这可能是您的解决方案。
如果您正在寻找一个在 Models.CurrentStanding 和 Models.UserInfo 都准备就绪之前不应创建 LeageBar.UserInfo 实例的解决方案,您 必须 return fetch 函数的结果,因此您可以从 setHandlers 中删除调用 fetch 并按如下方式使用它们:
this.standings = App.request('collection:currentStandings'); this.userInfo = App.request('model:userInfo'); var that=this; that.standings.fetch().done(function(){ that.userInfo.fetch().done(function(){ that.standings.each(function(s) { if (s.currentUser) { //.... } }); userInfoView = new LeagueBar.UserInfo({ collection: that.standings }); });