2013-10-25 15 views
6

Uno dei miei AngularJS controllori contiene questa linea:In attesa di promessa di risolvere prima risorsa carico

api.tickets.query() 

modulo api contiene questo:

angular.module('myapp.api', [ 
    'ngResource' 
]) 

.factory('api', function($resource, applicationsService) { 

    function fetchAppId() { 
    return applicationsService.getCurrentApp(); 
    } 

    return { 
    tickets: $resource('tickets', { 
     applicationId: fetchAppId 
    }), 
    ... 
    } 

applicationsService.getCurrentApp() effettua una chiamata http $ si. Quindi puoi forse vedere il problema: questa chiamata potrebbe non essere stata risolta dal momento in cui fetchAppId() restituisce.

Come posso aggirare questo?

risposta

6

Diciamo dati che torna dal applicationsService attraverso asincrona è:

var data = [ 
    { 
     "PreAlertInventory": "5.000000", 
     "SharesInInventory": "3.000000", 
     "TotalSharesSold": "2.000000" 
    } 

e applicationsService ritorna fabbrica promettono:

.factory('applicationsService', ['$resource','$q', function($resource, $q) { 
    var data = [ 
    { 
     "PreAlertInventory": "5.000000", 
     "SharesInInventory": "3.000000", 
     "TotalSharesSold": "2.000000" 
    } 
    ]; 

     var factory = { 
      getCurrentApp: function() { 
       var deferred = $q.defer(); 

       deferred.resolve(data); 

       return deferred.promise; 
      } 
     } 
     return factory; 
}]); 

Vorrei solo chiamare api.tickets()

$scope.data = api.tickets(); 

ma il nostro servizio api sarà simile:

.factory('api', function($resource, applicationsService,$q, $timeout) { 

    function fetchAppId() {  
     return applicationsService.getCurrentApp(); 
    } 

    return { 
tickets: function() { 
     var deferred=$q.defer(); 
     fetchAppId().then(function(data) { // promise callback 
      $timeout(function(){   // added dummy timeout to simulate delay 
        deferred.resolve(data);  
       }, 3000);      
     }); 
     return deferred.promise; 
    } 
    } 
}); 

Demo Fiddle

+0

Bingo, grazie Maxim, ha funzionato come un fascino. Apprezzo il violino e il dettaglio :) –

+0

Penso che funzioni perché la promessa in $ scope è attesa per il ciclo $ apply(). Come dice la documentazione, "$ q è integrato con il meccanismo di osservazione del modello $ rootScope.Scope Scope in angolare, il che significa una propagazione più veloce della risoluzione o del rifiuto nei modelli ed evitare inutili ridondazioni del browser, il che comporterebbe un'interfaccia utente tremolante". – Plap

+0

se qualcuno usa $ resource per richiesta, allora dobbiamo includere $ promise fetchAppId(). $ Promise.then (function (data) {----}); –

4

È necessario creare una promessa.

.factory('api', function($resource, applicationsService,$q) { 

    function fetchAppId() { 
    return applicationsService.getCurrentApp(); 
    } 

    return { 
    tickets: function() { 
     var defer=$q.defer(); 
     fetchAppId().then(function(data) { 
      var appId=data; 
      $resource('tickets', {applicationId: appId}) 
       .then(function(data) { 
         defer.resolve(data); 
       }) 
     } 
     return defer.promise; 
    } 
    } 
1

Se si desidera attendere una risorsa angolare ($resource) da risolvere prima di un cambiamento percorso, allora si' Dovrai restituire lo $promise.

$routeProvider.when('/tickets', { 
    resolve: { 
     'tickets': function ('Ticket') { 
      // do this to resolve the async call prior to controller load 
      return Ticket.query().$promise; 

      // this will resolve 'tickets' during/after controller load 
      return Ticket.query(); 
     } 
    }, 
    controller: ... 
}); 
Problemi correlati