2014-11-07 12 views
11

Wie kann ich meine angularjs App in Verbindung mit der Antwort einer GET-Anfrage initialisieren.

Zum Beispiel: -

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

Ich mag die Konstante setzen, während meine Anwendung initialisiert, und in der Lage, die konstant über meine Komponenten zu teilen.

Was ist der beste Ansatz, um dies zu erreichen?

+0

was 'theValueFromHttpCall'? – akonsu

+0

@akonsu Die Frage wurde aktualisiert. In meinem Fall wäre die Antwort ein JSON-Objekt. –

+0

interessant. Ich würde vermuten, dass der Injektor bereits alle Komponenten beim Booten definiert hat, also denke ich, dass es notwendig ist, direkt mit ihm zu arbeiten, um dein Szenario zu aktivieren. – akonsu

Antwort

5

Das Ergebnis von $http.get ist nicht verfügbar, während die App initialisiert wird. Es ist nur verfügbar, wenn der Server es liefert. Aus diesem Grund ist es einfach unmöglich, diesen Wert in einem Modul konstant zu halten. Sie laufen das Risiko von

Was Sie jedoch tun können, ist den Anruf um $http.get in einem Dienst zu wickeln und diesen Dienst injizieren, wo immer Sie die Konstante möchten. (Beachten Sie, dass Leistungen nicht in Config-Blöcke injiziert werden.)

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

Der etwas umständlich Modus der Wert Ihres almostConstant zugreifen zu seiner asynchronen Natur zurückzuführen ist. Es ist einfach zu einem unbestimmten Zeitpunkt verfügbar, so dass der Versuch, auf synchrone Weise darauf zuzugreifen, eine Menge subtiler Timing-Bugs einführt.


Eine sehr nicht angular-ish Weg dies zu tun wäre, Ihre Konstante in der JS-Datei direkt zu schreiben. Im Moment kann Ihr Server eine Anfrage an 'url' mit einem Wert beantworten.

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

wo Ergebnis ist offensichtlich Ihre Konstante: Stattdessen könnte man es auf eine Anfrage zu 'url.js' mit der folgenden Zeichenkette machen beantworten. Wenn Sie zum Beispiel PHP im Backend wurden verwendet, könnte es etwa so aussehen:

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

Vergewissern Sie sich, dass die Konstante sieht tatsächlich wie ein JavaScript-Wert. Wenn es sich um eine Zeichenfolge ist, wickeln Sie es in ', wenn es sich um ein JSON-Objekt schreiben seine Serialisierung ist usw.

Danach Sie einfach ein Skript-Tag enthalten Hinweis auf url.js in Ihrer index.html Datei.

Beachten Sie, dass diese Lösung synchron ist. Wenn das Abrufen der Konstante auf dem Server eine Weile dauert, wirkt sich dies auf die Ladezeit Ihrer Seite aus.

+0

In meinem Fall gibt es keine serverseitigen Webseiten. Also denke ich, dass ich mit dem ersten Ansatz, den Sie vorgeschlagen haben, gehen muss. –

+0

Sie rufen den Server jedes Mal an, wenn Sie einen konstanten Wert lesen möchten, keine gute Lösung. – Abhijeet

+0

@Abhijeet Die Factory-Methode wird nur einmal aufgerufen, daher wird auf der Seite ein einzelner Aufruf von "$ http.get" ausgeführt, sodass eine einzelne Anfrage an den Server gesendet wird. Probieren Sie es einfach in einem einfachen Beispiel aus. – Tibos

1

Ich fand heraus, dass die Verwendung von "resolve" -Eigenschaften entweder in standardmäßigen eckigen Routern oder während der Verwendung von UI-Router eine bessere Möglichkeit ist, Ihre App zu initialisieren.

Dies ist, wie haben während UI-Router mit: -

  1. wie diese abstrakten Zustand mit leerer Inline-Vorlage, um einen Top-Level definieren: -
$stateProvider.state('root',{ 
    abstract:true, 
    template:'<ui-view/>', 
    resolve : { 
     securityContext : function($http){ 
      return $http.get("/security/context"); 
     } 
    } 
}); 
}); 

Das Anwesen gelöst werden, sind etwas, das durch Ihre Anwendung erforderlich ist. Wie - Sicherheitstoken, aktuell angemeldeter Benutzer usw.

  1. Definieren Sie den Kindstatus, der vom obigen Status erbt. Jeder Teil Ihrer Anwendung muss von einem Staat verwaltet werden.
$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

Wie in this blog post erklärt, können Sie eine Konstante vor Bootstrapping App init:

(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"]); 
      }); 
     }); 


}()); 
Verwandte Themen