2014-11-07 2 views
0

У меня есть пример, который загружает некоторые данные из локальных файлов глобальной функцией loadJSON (будучи глобальным не является обязательным, но предпочтительным).

После этого я жду, пока загрузятся данные из всех документов, и напечатайте строку 'i ve loaded'.

Проблема в том, что я начинаю использовать данные из службы «x» раньше, чем мне удается полностью загрузить ее в память из файлов.

Как подождать, пока данные будут загружены, и только после этого продолжить отображение страниц и выполнение всего?

Для этого мне нужно использовать $q, но как это сделать?

function loadJSON(file, callback) { 
    var doc = new XMLHttpRequest(); 
    doc.overrideMimeType("application/json"); 
    doc.open('GET', file, true); 
    doc.onreadystatechange = function() { 
    if (doc.readyState == 4 && doc.status == "200") { 
     callback(JSON.parse(doc.responseText)); 
    } 
    }; 
    doc.send(null); 
} 

angular 
    .module('msApp') 
    .factory('service.x', [ 
    function() { 
     var _database = {}; 

     return { 
     get: function (k1, k2) { 
      return _database[k1][k2]; 
     }, 

     load: function (list, callback) { 
      var length = list.length; 
      var loaded = 0; 

      function addToDB(name) { 
      var url = './assets/{0}.json'.format(name); 
      loadJSON(url, function (json) { 
       _database[name] = json; 

       loaded++; 
       if (length === loaded && callback) callback(); 
      }); 
      } 

      for (var i = 0; i < list.length; i++) { 
      addToDB(list[i]); 
      } 
     } 

     }; 
    } 
    ]); 

angular 
    .module('msApp', []) 
    .run([ 
    '$rootScope', 
    'service.x', 
    function ($rootScope, x) { 

     x.load($rootScope.services, function() { 
     console.log('i ve loaded') 
     }); 

    } 
    ]) 
    .config(function ($routeProvider) { 

    $routeProvider 
     .when('/sign', { 
     templateUrl: '../views/sign.html', 
     controller: 'signCtrl' 
     }) 
     .when('/a', { 
     templateUrl: '../views/a.html', 
     controller: 'aCtrl' 
      .otherwise({ 
      redirectTo: '/signin' 
      }); 
    }); 
+0

Почему вы не используете $ http для загрузки данные – harishr

+0

не видят, как это связано с вопросом. Becouse использует этот метод. я просто скопировал часть, которая требуется на вопрос – euvl

ответ

1

контроллеры принимают параметр resolve, который позволяет вводить зависимости в контроллеры, которые могут быть сырыми объектами или обещаниями, который блокирует инстанциацию контроллера до тех пор, пока не будет устранен:

$routeProvider.when('/routeA', { 
    templateUrl: '/routeA.html', 
    controller: 'controllerA', 
    resolve: { 
    mydata: ['service.x', function (x) { 
     return x.load($rootScope.services); 
    }] 
    } 
}); 

в load и addToDb функции должны быть изменены для возврата обещаний:

load: function (list) { 
    // instantiate variables 

    function addToDb(name) { 
    var deferred = $q.defer(); 
    // build url from name 

    loadJson(url, function (data) { 
     // save to database 

     deferred.resolve(data); 
    }); 

    return deferred.promise; 
    } 

    var promises = []; 
    for (var i = 0; i < list.length; i++) { 
    promises.push(addToDb(list[i])); 
    } 

    return $q.all(promises); 
} 
+0

спасибо, очень полезно – euvl

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