2013-11-22 9 views
10

Ich verwende mehrere Angular JS $ -Ressourcendefinitionen, die alle ihre Basis-URL von einem Konfigurationsdienst abrufen. Zum Beispiel:

$resource(config.baseURL() + '/api/v2/foo/:id', {id: '@id'}) 

$resource(config.baseURL() + '/api/v2/bar/:id', {id: '@id'}) 

Der Grund dies geschehen ist, ist, dass die Basis-URL kann über einen Query-String-Parameter geändert werden, wenn die Anwendung zuerst geladen wird.

habe ich herausgefunden, dass (natürlich im Nachhinein) der URL durch die $ Ressource verwendet wird nur einmal initialisiert, so ist es möglich, eine Race-Bedingung zu erhalten, wo die URL für eine bestimmte $ resource vor die Basis-URL Query-String initialisiert wird Parameter wird behandelt. Also habe ich versucht, die $ Ressource Erklärung, dies zu ändern:

$resource(':baseURL/api/v2/foo/:id', {baseURL: config.baseURL(), id: '@id'}) 

Leider ist die Basis-URL ist entkam immer - die //-%2F%2F umgewandelt wird - so die ganze URL dann nicht richtig funktioniert.

Gibt es eine Möglichkeit, das Entweichen für diesen Parameter zu unterdrücken? (Oder vielleicht ein besserer Weg, um das Problem in der Regel zu lösen)?

+0

Warum hat Ihr baseURL selbst ändern? –

+1

Es ist eine taktische Lösung zur Unterstützung mehrerer Umgebungen. d. h. ich kann eine Instanz leicht auf eine Staging-API verweisen, wenn ich etwas debuggen muss. Nicht ideal und ich suche eine längerfristige Lösung. –

+0

Sie können versuchen, den http: // Teil in den ersten Parameter einzubetten und den Rest des Teils von config.baseURL() zu übergeben und zu überprüfen, ob er funktioniert. – Chandermani

Antwort

0

Warum nicht die Verwendung des $ location Service machen?

Zum Beispiel, wie wäre es mit den folgenden, um die Basis-URL zu behandeln, und, wenn die Anwendung von localhost läuft, die Port-Nummer? Darüber hinaus können, umfassen entweder http oder https basierend auf der aktuellen URL?

var host = $location.host(); 
if (host === "localhost") 
    host += ":" + $location.port(); 
var url = $location.protocol() + "://" + host + "/whateverElseYouWantInThePath"; 

und dann url verwenden, wo Sie es brauchen?

0

aus der Definition der Ressource, URL

  • @param {string} Eine parametrisierte URL-Vorlage mit von : wie in
  • /user/:username Präfix Parameter. Wenn Sie eine URL mit einer Portnummer verwenden (beispielsweise
  • http://example.com:8080/api), müssen Sie den Doppelpunkt vor dem Hafen
  • Zahl zu entkommen, wie folgt aus: djResource('http://example.com\\:8080/api').

So haben Sie Ihre config.baseURL() wie folgt zu definieren,

config.baseUrl = function(){ 
    return 'http://server.com\\:port/rest_part/'; 
} 
0

hier ein schrecklich ist aber die Arbeit Abhilfe. Statt ...

$resource(config.baseURL() + '/api/v2/foo/:id', {id: '@id'}) 

..., die nur einmal ausgewertet wird, ein Objekt verwenden, die String-Methoden implementiert, die ngResource vor jeder Anforderung auswertet:

var url = {}; 
url.value = function() {return config.baseURL() + '/api/v2/foo/:id'}; 
url.split = function (separator,limit) { return url.value().split(separator,limit) }; 
url.replace = function (match, other) { return url.value().replace(match, other) }; 
url.toString = function() { return url.value(); } 
$resource(url, {id: '@id'}) 
2

Eine weitere Möglichkeit, bewältigen kann dies Verwenden Sie einen Provider und konfigurieren Sie es in der Config Bühne.

Hier ist ein Beispiel für etwas Ähnliches, das ich vor einiger Zeit gemacht habe.

.provider('Environment', function() { 
    var environments = { 
     dev: { 
      root: 'http://localhost', 
      port: 3000, 
      api: '/api', 
      version: 'v1' 
     } 
    }; 
    var selectedEnv = 'dev'; 
    var self = this; 

    this.setEnvironments = function (envs) { 
     if (!Object.keys(envs).length) 
      throw new Error('At least one environment is required!'); 

     environments = envs; 
    }; 

    this.setActive = function (env) { 
     if (!environments[env]) 
      throw new Error('No such environment present: ' + env); 

     selectedEnv = env; 
     return self.getActive(); 
    }; 

    this.getEnvironment = function (env) { 
     if (!env) 
      throw new Error('No such environment present: ' + env); 
     return environments[env]; 
    }; 

    this.getActive = function() { 
     if (!selectedEnv) 
      throw new Error('You must configure at least one environment'); 

     return environments[selectedEnv]; 
    }; 

    this.getApiRoute = function() { 
     var active = self.getActive(); 
     return active.root + (active.port ? ':' + active.port : '') + 
      active.api + (active.version ? '/' + active.version : ''); 
    }; 

    this.$get = [function() { 
     return self; 
    }]; 
}) 

Dann in der Konfigurationsphase:

.config(function (EnvironmentProvider) { 

    EnvironmentProvider.setEnvironments({ 
     dev: { 
      root: 'http://10.0.0.3', 
      api: '/api', 
      version: 'v1' 
     }, 
     localonly: { 
      root: 'http://localhost', 
      api: '/api', 
      version: 'v1' 
     }, 
     prod: { 
      root: 'https://myapp.mybackend.com', 
      api: '/api', 
      version: 'v1' 
     } 
    }); 

    //Set prod as the active schema 
    EnvironmentProvider.setActive('prod'); 
}); 

Später in einigen Controller/service/Fabrik:

.factory('API',function($resource, Environment){ 
return { 
    User: $resource(Environment.getApiRoute() + '/users/:id', {id: '@_id'}), 
    OtherResource: $resource(Environment.getApiRoute() + '/otherresource/:id', {id: '@_id'}) 
} 
}); 
+1

Dies ist eine großartige Lösung! –