在Javascript中本地更新全局变量

时间:2014-12-29 20:53:04

标签: javascript backbone.js global-variables variable-assignment

我开始通过实现一个简单的项目来学习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});

4 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

尝试使用:{async: false} // Ajax-JQuery: Perform an asynchronous HTTP (Ajax) request

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

让我知道它是否有效。

答案 2 :(得分:0)

检查控制台输出,如果AJAX调用按设计工作,您应该看到Total:0 优先然后是预期值。这是按设计工作的,因为在函数调用fetch完成后,fetch选项中的回调函数将被称为

根据您的设计,您不需要全局变量total,因为主干集合支持.length约定。请参阅http://backbonejs.org/#Collection-length当您的提取功能完成时。见http://backbonejs.org/#Collection-fetch

答案 3 :(得分:0)

我认为您正在寻找的是一种在视图中的任何位置操纵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
  }
});

由于collection fetch是ajax GET的包装器(除非你覆盖Backbone.sync),它将异步运行。如果你想与fetch同步运行代码,你可以做三件事。

  1. 像在代码中一样使用回调函数
  2. 使用延迟/承诺回调(非常类似于1.)
  3. 执行@KimGysen所说的内容:Backbone具有用于设置和响应事件的可靠API。 (Marionettejs在非常酷的方向扩展了这个API)。