2013-08-02 5 views
12

Ich muss einige Informationen (ein Schema) vom Server abrufen, bevor ich eine Reihe von Diensten einrichten, die von diesen Informationen abhängig sind.Ein gelöstes Versprechen in Dienst einfügen

Mein Server bietet ein Schema, das verschiedene Eigenschaften eines Modells definiert. In meinem Winkel Code habe ich einen Dienst, der dieses Schema wird:

services.factory('schema', function($q, $http) { 
    var deferred = $q.defer(); 
     $http.get('schema/').then(function(response) { 
     schema = // some function of response.data 
     deferred.resolve(schema); 
    }, function() { 
     deferred.reject('There was a problem fetching the schema'); 
    }); 
     return deferred.promise; 
}); 

Ich möchte injizieren das Schema-Objekt und nicht das Versprechen, in andere Dienste, die auf dem Schema ab. $ RouteProvider können wir tun dies für Controller:

app.config(function($routeProvider) { 
    $routeProvider. 
     when('/', { 
      controller: 'SomeCtrl', 
      resolve: { 
       schema: 'schema' 
      }, 
      ... 
     }); 
}); 

und dies ermöglicht es mir SomeCtrl wie folgt zu definieren:

controllers.controller('SomeCtrl', function($scope, schema) { 
    // schema is an object 
    ... 
}); 

Aber für Dienstleistungen, ich zu tun habe:

services.factory('SomeService', function(schema) { 
    // schema is a promise 
    schema.then(function(schema) { 
     ... 
    }); 
}); 

Ist Kann ich das irgendwie machen?

+0

Nein, das ist nur, wie es funktioniert, zumindest vorerst. – aet

+0

Der eckige Router wartet darauf, dass die Werte in 'resolve' aufgelöst/zurückgewiesen werden, bevor der Controller instanziiert wird. Dann verwendet es lokale Werte, um in den Controller zu injizieren (der Winkelinjektor bevorzugt Einheimische). TL; DR: Du arbeitest mit zwei verschiedenen Schemas. –

Antwort

-1

Sie erhalten ein Versprechen, weil Ihre Service-Funktion sofort seinen Körper bewertet, wenn Sie ihn aufrufen (wie Funktionen tun). Normalerweise sollte ein Dienst ein Objekt zurückgeben, so dass der Benutzer (ein anderer Dienst, Controller oder was auch immer) dann die Funktionen für dieses Objekt bei Bedarf aufrufen kann.

services.factory('schema', function($q, $http) { 
return { 
    get: function() { 
    var deferred = $q.defer(); 
    $http.get('schema/').then(function(response) { 
     schema = // some function of response.data 
     deferred.resolve(schema); 
    }, function() { 
     deferred.reject('There was a problem fetching the schema'); 
    }); 
    return deferred.promise; 
    } 
} 

});

+0

In Ihrem Beispiel gibt die Methode 'get' immer noch ein Versprechen zurück, nicht die Auflösung des Versprechens, was die Frage ist. –

5

Was Sie wollen, ist Deferred Bootstrap. Zu diesem Zweck gibt es bereits ein Plugin - https://github.com/philippd/angular-deferred-bootstrap.

Ich erstelle ein Beispiel an plunkr - http://plnkr.co/edit/VfISHNULXRLe52NeAsn1?p=preview

* Sie müssen bestehenden ng-App mit latentem Bootstrap

Code Snippet ersetzen -

angular.element(document).ready(function() { 
    deferredBootstrapper.bootstrap({ 
     element: document.body, 
     module: 'plunker', 
     resolve: { 
      schema: ['$http', 
       function($http) { 
        return $http.get('schema.json'); 
       } 
      ] 
     } 
    }); 
}); 

Dann können Sie Schema verwenden sowieso in Controller , Services oder Fabrik genau wie Route auflösen.

Beispielcode für Fabrik

app.factory('SomeService', function(schema){ 
    return { 
     getTitle: function() { 
      return schema.title; 
     } 
    } 
}); 
+0

Genau das, was ich gesucht habe, danke - das verzögerte Bootstrapping funktioniert wie ein Zauber mit dieser Komponente! – conceptdeluxe

Verwandte Themen