0

Я начал изучать библиотеку Backbone.js, выполнив простой проект. Увидев несколько учебников, я выпустил код, который показан ниже. Я знаю, что это может выглядеть не идеально, поскольку я новичок в разработке javascript.Обновление глобальной переменной локально в 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}); 
+1

Таким образом, вы заказываете доставку пиццы по телефону. Вы пытаетесь съесть пиццу перед ее доставкой. Он асинхронный, вы читаете значение до его установки. Вот почему существует метод успеха. – epascarello

+0

Вот почему я разместил этот вопрос :) Я хотел бы узнать, как я могу изменить этот код, чтобы заставить его работать. Спасибо –

+0

Посмотрите на обещания. – epascarello

ответ

0

Checkout вывод на консоль, вы должны увидеть Total:0первого то ожидаемого значения, если AJAX вызов работает, как задумано. это работает так, как было разработано, так как функция обратного вызова в параметрах выборки будет называться после, завершает вызов функции fetch.

В соответствии с вашим дизайном вам не нужна глобальная переменная total, так как поддержка базовой линии поддерживает .length конвенция. см. http://backbonejs.org/#Collection-length Когда функция выборки завершена. см. http://backbonejs.org/#Collection-fetch

+0

Спасибо. Документация Backbone действительно удобна, если честно работать. Я использую длину, чтобы получить общее число. Тем не менее, мне нужно будет получить общее количество всех идентификаторов. Что еще более важно, я пытаюсь работать с оператором присваивания. Например, второй общий «" console.log («Total:» total); «» выполняется первым, а не предыдущим. Я прочитал ряд статей об этом. В конечном счете, я ищу, чтобы найти решение для обновления переменной локально и иметь возможность использовать обновленное значение на верхнем уровне. –

1

Магистраль пытается продвигать подход, управляемый событиями.
Я думаю, что в конечном итоге вы получите агрегатор событий;

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

Поскольку сбора выборки является оболочкой для Ajax GET (если вы не перегрузите Backbone.sync) он будет работать асинхронно. Если вы хотите запустить синхронизацию кода с помощью извлечения, вы можете сделать три вещи.

  1. Использование функции обратного вызова, как вы делаете в коде
  2. Использование Отложенный/Обещания обратные вызовы (очень похож на 1.)
  3. Делайте то, что @KimGysen «s говорит: Магистраль имеет солидный API для создания и реагирования к событиям. (Marionettejs расширяет этот API в очень прохладных направлениях).
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

Позвольте мне знать, если он работает.

Смежные вопросы