在 Javascript 中本地更新全局变量

Updating global variable locally in Javascript

本文关键字:更新 全局变量 Javascript      更新时间:2023-09-26

我通过实现一个简单的项目开始学习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. 像在代码中使用回调函数一样
  2. 使用延期/承诺回调(与 1 非常相似。
  3. 按照@KimGysen所说的去做:Backbone有一个可靠的API来设置和响应事件。(Marionettejs 在非常酷的方向上扩展了这个 API)。