2013-11-22 65 views
10

我使用了幾個Angular JS $資源定義,所有這些定義都從配置服務中檢索其基本URL。例如:

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

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

這樣做的原因是,基本URL可以通過查詢字符串參數來改變第一次加載應用程序時。

我想通了,(顯然回想起來)由$資源使用的URL進行初始化只有一次,因此有可能得到其中特定$資源的URL被基本URL查詢字符串初始化之前的競爭條件參數處理。於是,我就在$資源聲明改成這樣:

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

不幸的是,基本URL是越來越逃脫 - 在//轉換爲%2F%2F - 所以整個URL,然後無法正常工作。

有什麼辦法可以抑制該參數的轉義嗎? (或者更好的方式來解決一般問題)?

+0

爲什麼你連基本URL改變? –

+1

這是支持多種環境的戰術解決方案。即,如果我需要調試某些東西,我可以輕鬆地將實例指向臨時API。不理想,我正在尋找更長期的解決方案。 –

+0

您可以嘗試將http://部分嵌入到第一個參數中,並從config.baseURL()傳遞該部分的其餘部分並查看它是否有效。 – Chandermani

回答

0

爲什麼不使用$ location服務?

例如,如何處理基礎url,並且如果應用程序從localhost運行,那麼包含端口號?另外,能夠根據當前URL包含http或https?

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

然後用url你需要它嗎?

0

從資源的定義,

  • @param {string}裏的URL與:前綴參數一個參數化的URL模板在
  • /user/:username。如果您使用的URL與端口號(如
  • http://example.com:8080/api),你需要的端口之前轉義冒號
  • 號,這樣的:djResource('http://example.com\\:8080/api')

所以,你必須確定你的config.baseURL()如下,

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

這是一個可怕的,但工作的解決方法。而不是...

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

...其中只計算一次,使用實現字符串的方法是ngResource每個請求之前評估的對象:

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

另一種方式則可以解決這使用供應商並將其配置在配置階段。

這是一個類似的例子,我做了一段時間後。

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

然後在配置階段:

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

在某些控制器/服務/工廠後來:

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

這是一個很好的解決方案! –