参数化Angularjs $资源中的基本URL

时间:2013-11-22 10:09:41

标签: angularjs

我正在使用几个Angular JS $资源定义,所有这些定义都从配置服务中检索它们的基本URL。例如:

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

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

这样做的原因是,首次加载应用程序时,可以通过查询字符串参数更改基本URL。

我发现(显然回想起来)$ resource使用的URL只被初始化一次,因此可以获得一个竞争条件,其中特定$资源的URL在之前初始化处理基本URL查询字符串参数。所以我尝试将$ resource声明更改为:

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

很遗憾,基本网址已被转义 - //已转换为%2F%2F - 因此整个网址无效。

有没有办法抑制该参数的转义? (或者也许是解决问题的更好方法)?

4 个答案:

答案 0 :(得分: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 :(得分:0)

为什么不使用$ location服务?

例如,如何处理基本URL,以及如果应用程序从localhost运行,请包含端口号?此外,能够根据当前URL包含http或https吗?

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

然后在需要的地方使用url

答案 2 :(得分:0)

从资源定义

  • @param {string} 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/';
}

答案 3 :(得分:0)

这是一个可怕但有效的解决方法。而不是......

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

...只评估一次,使用一个对象来实现ngResource在每个请求之前评估的String方法:

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