2014-11-07 8 views
11

Come posso inizializzare la mia app angularjs contant con la risposta di una richiesta GET.

Ad esempio: -

angular.module('A',[]); 
    angular.module('A').run(function ($rootScope,$http){ 
     $rootScope.safeApply = function (fn) { 

       $http.get('url').success(function(result){ 

        // This doesn't work. I am not able to inject 'theConstant' elsewhere in my application 
        angular.module('A').constant('theConstant', result); 
       });     
       var phase = $rootScope.$$phase; 
       if (phase === '$apply' || phase === '$digest') { 
        if (fn && (typeof (fn) === 'function')) { 
         fn(); 
        } 
       } else { 
        this.$apply(fn); 
       } 
      }; 
     }); 

voglio impostare la costante mentre la mia app inizializzato ed essere in grado di condividere il costante attraverso i miei componenti.

Qual è l'approccio migliore per raggiungere questo obiettivo?

+0

ciò che è 'theValueFromHttpCall'? – akonsu

+0

@akonsu Aggiornamento della domanda. Nel mio caso, la risposta sarebbe un oggetto JSON. –

+0

interessante. Direi che l'iniettore ha già tutti i componenti definiti all'avvio, quindi penso che sia necessario lavorarci direttamente per abilitare il tuo scenario. – akonsu

risposta

5

Il risultato di $http.get non è disponibile mentre l'app è inizializzata. È disponibile solo quando il server lo consegna. Per questo motivo è semplicemente impossibile mantenere quel valore in una costante di modulo. Corri il rischio di

Ciò che puoi fare, tuttavia, è racchiudere la chiamata a $http.get in un servizio e iniettare quel servizio ovunque tu voglia la costante. (Si noti che i servizi non possono essere iniettati in blocchi di configurazione.)

// grab the "constant" 
angular.module('A').factory('almostConstant', function() { 
    return $http.get('url').then(function(response) { 
    return response.data; 
    }); 
}); 

// use the "constant" 
angular.module('A').controller('controller', function($scope, almostConstant) { 
    almostConstant.then(function(data){ 
    $scope.almostConstant = data; 
    }); 
}); 

La modalità leggermente scomodo per accedere al valore del almostConstant è dovuta alla sua natura asincrona. Semplicemente è disponibile in un tempo non specificato, quindi provare ad accedervi in ​​modo sincrono può introdurre molti piccoli bug temporali.


Un modo molto non angolare di farlo sarebbe scrivere direttamente la costante nel file JS. Al momento il tuo server può rispondere a una richiesta a 'url' con un valore. Invece, si potrebbe rendere risposta ad una richiesta di 'url.js' con la seguente stringa:

angular.module('A').constant('theConstant', result); 

cui risultato è, ovviamente, la vostra costante. Per esempio, se si sta utilizzando PHP sul back-end che potrebbe essere simile a questa:

<?php 
    header('Content-Type: application/javascript'); 
    $constant = retrieveMyConstant(); 
?> 
angular.module('A').constant('theConstant', <?php echo $constant; ?>); 

Assicurarsi che la costante si presenta come un valore JavaScript. Se si tratta di una stringa, avvolgerlo in ', se si tratta di un oggetto JSON scrivere la sua serializzazione, ecc

Dopo questo si include semplicemente un tag script che punta al url.js nel file index.html.

Si noti che questa soluzione è sincrona, quindi se il recupero della costante sul server richiede un po ', ciò influirà sul tempo di caricamento della pagina.

+0

Nel mio caso non ci sono pagine web lato server. Quindi penso che dovrò andare con il primo approccio che hai suggerito. –

+0

Si sta chiamando il server ogni volta che si desidera leggere un valore costante, non una buona soluzione. – Abhijeet

+0

@Abhijeet Il metodo factory viene chiamato una sola volta, in modo da una singola chiamata a '$ http.get' viene effettuata sulla pagina, in modo da una singola richiesta viene inviata al server. Sentiti libero di provarlo con un semplice esempio. – Tibos

1

Ho scoperto che l'utilizzo di proprietà 'risoluzione' nel router angolare standard o durante l'utilizzo di UI-Router è un modo migliore per inizializzare l'app.

Questo è come ha fatto durante l'utilizzo di UI-Router: -

  1. Definire uno stato astratto di alto livello con il modello in linea vuota in questo modo: -
$stateProvider.state('root',{ 
    abstract:true, 
    template:'<ui-view/>', 
    resolve : { 
     securityContext : function($http){ 
      return $http.get("/security/context"); 
     } 
    } 
}); 
}); 

La proprietà essere risolti sono qualcosa che è richiesto attraverso la tua applicazione. Mi piace - token di sicurezza, utente attualmente connesso, ecc.

  1. definire lo stato del bambino che eredita da sopra dello Stato. Ogni singola parte della tua domanda deve essere gestita da uno stato.
$stateProvider.state('root.optosoft.home',{ 
    url:'/home', 
    templateUrl : '/assets/home-module/partial/home/home.html', 
    controller: 'HomeCtrl', 
    resolve : { 
     accounts : function(securityContext){ 
      // Child state wil first wait for securityContext to get resolved first 
     } 
    } 
}); 
5

Come spiegato in this blog post, è possibile init un costante prima bootstrapping la vostra applicazione:

(function() { 
    var app = angular.module("A", []); 

    var initInjector = angular.injector(["ng"]); 
    var $http = initInjector.get("$http"); 

    return $http.get("/path/to/data.json") 
     .then(function(response) { 
      app.constant("myData", response.data); 
     }) 
     .then(function bootstrapApplication() { 
      angular.element(document).ready(function() { 
       angular.bootstrap(document, ["A"]); 
      }); 
     }); 


}()); 
Problemi correlati