我通过实现一个简单的项目开始学习Backbone.js库。在看了一些教程后,我制作了如下所示的代码。我知道它可能看起来并不完美,因为我是javascript开发的新手。
因此,在下面,我从API中获取国籍列表,然后获取来自这些特定国家的学生人数。这暂时似乎很清楚,但问题是,我需要获取每个国籍的学生总数,这就是为什么在第二个集合获取函数中有一个计数器的原因。我面临的问题是关于Javascript的。基本上,全局定义"总计"并在本地更新它是我需要做的。我遇到了许多与此类似的线程,但老实说,我理解得不够好,无法重现我自己的解决方案。再一次,我的问题是如何重新设计这段代码,以便我可以在本地更新变量"total"的值,然后在内部获取函数之外使用更新的结果。感谢您的回答和建议。提前谢谢。
$.ajaxSetup({
crossDomain : true,
cache : false,
contentType : "application/json",
dataType : "json"
});
var baseURL = "http://lucalongo.eu:80/courses/2014-2015/questionnaireDIT/app/index.php";
var mModel = Backbone.Model.extend({});
var cNationality = Backbone.Collection.extend({
model: mModel,
url: this.baseURL + "/nationalities"
});
var cStudent = Backbone.Collection.extend({
model : mModel,
initialize : function(models, options) {
this.url = "http://lucalongo.eu:80/courses/2014-2015/questionnaireDIT/app/index.php/students/nationality/" + options.id;
}
});
var vView = Backbone.View.extend({
render: function(){
var total = 0;
this.collection = new cNationality();
this.collection.fetch({
success: function(c){
_.each(c.models, function(col) {
var nationalDesc = col.toJSON().description;
var nationalID = col.toJSON().id;
var studentNationality = new cStudent([], {id : nationalID});
studentNationality.fetch({
success: function(c){
//console.log(nationalDesc + ": " + c.length);
total = total + c.length;
console.log(total);
}
});
});
}
});
console.log("Total:" total); // still displays 0
}
});
var v = new vView();
v.render();
Backbone.history.start({pushState: true});
Backbone试图推广事件驱动的方法。
我认为您最终会得到一个事件聚合器;
window.APP = {};
APP.vent = _.extend({}, Backbone.Events);
APP.vent.on("update:counter", function(increment){
APP.counter = APP.counter + increment;
});
从调用代码中,触发事件:
var increment = 5 //Just an example
APP.vent.trigger("update:counter", increment);
尝试使用: {async: false}
//Ajax-JQuery: 执行异步 HTTP (Ajax) 请求
this.collection.fetch({async: false}, {
success: function(c) {
_.each(c.models, function(col) {
var nationalDesc = col.toJSON().description;
var nationalID = col.toJSON().id;
var studentNationality = new cStudent([], {
id: nationalID
});
studentNationality.fetch({
success: function(c) {
//console.log(nationalDesc + ": " + c.length);
total = total + c.length;
console.log(total);
}
});
});
}
});
可能对您有帮助的链接:Backbone.Sync
让我知道它是否有效。
查看控制台输出,如果 AJAX 调用按设计工作,您应该首先看到Total:0
然后是预期值。 这按设计工作,因为 fetch 选项中的回调函数将在函数调用完成后调用fetch
。
根据您的设计,您不需要全局变量total
因为主干集合支持.length
约定。 请参阅 http://backbonejs.org/#Collection-length 当您的抓取功能完成时。 请参阅 http://backbonejs.org/#Collection-fetch
我认为您正在寻找的是一种在视图中任何位置操作total
的方法。在我希望变量对我的所有视图方法都是"全局"的情况下,我倾向于做的是使其成为视图的属性。我要说的是,
var vView = Backbone.View.extend({
initalize: function(){
// Initialize your object property
this.totalCount = 0;
},
render: function() {
// Inside callbacks you will lose your view context
// so save it
var that = this;
// Nested collection fetch
success: function(c){
that.totalCount = that.totalCount + c.length;
console.log(that.totalCount);
}
// rest of code
}
});
由于集合获取是 ajax GET 的包装器(除非您覆盖Backbone.sync
),它将异步运行。如果你想与fetch同步运行代码,你可以做三件事。
- 像在代码中使用回调函数一样
- 使用延期/承诺回调(与 1 非常相似。
- 按照
@KimGysen
所说的去做:Backbone有一个可靠的API来设置和响应事件。(Marionettejs 在非常酷的方向上扩展了这个 API)。