2014-11-25 4 views
3

В моем приложении Angular у меня есть служба, которая использует $http для извлечения данных с сервера. Конечная точка сервера использует HMAC-аутентификацию и ожидает, что параметры строки запроса будут в определенном порядке по URL-адресу.

Angular sorts the $http parameters when it builds the URL, поэтому не представляется возможным указать заказ пользовательских параметров.

Вот пример:

this.apiCall = function() { 
    return $http({ 
     method: 'GET', 
     url: 'http://example.com/url/v1/endpoint', 
     params: { 
      'c': 'cdata', 
      'a': 'adata', 
      'b': 'bdata' 
     } 
    }); 
}; 

Угловая построит URL в http://example.com/url/v1/endpoint?a=adata&b=bdata&c=cdata, но мне нужно, чтобы сохранить порядок Params, как указано, http://example.com/url/v1/endpoint?c=cdata&a=adata&b=bdata.

Я понимаю, что могу просто привязать параметры к строке URL вручную, но это не очень удобно, и это не позволяет легко управлять перехватчиками $http.

Угловой, вероятно, сортирует параметры для обеспечения единообразного поведения в реализациях браузера, поскольку в ECMAScript не указывается порядок объектов.

Независимо от того, Кто-нибудь знает, как обойти по умолчанию Угловое поведение сортировки параметров, чтобы создать URL-адрес, который сохраняет указанные параметры?

+0

Кажется, вы уже ответили на свой вопрос. Если посмотреть на связанный исходный код, очевидно, что единственный способ обеспечить соблюдение порядка параметров - это построить строку запроса самостоятельно и предоставить ее как часть URL-адреса. Вы можете создать декоратор для конфигурации '$ http', создавая конфигурацию при встрече с некоторым специальным синтаксисом' params'. – hon2a

+0

@ hon2a Да, я закончил тем, что создал декоратор для создания URL-адреса. –

ответ

3

Я улучшен ваше решение, чтобы создать что-то более поток подкладки и гарантировано работать:

$httpProvider.interceptors.push(function() { 
    return { 
     request: function (config) { 
      if (!config.paramOrder) { 
       return config; 
      } 

      // avoid leaking config modifications 
      config = angular.copy(config, {}); 

      var orderedParams = []; 
      config.paramOrder.forEach(function (key) { 
       if (config.params.hasOwnProperty(key)) { 
        orderedParams.push(encodeURIComponent(key) + '=' + encodeURIComponent(config.params[key])); 
        // leave only the unordered params in the `params` config 
        delete config.params[key]; 
       } 
      }); 

      config.url += (config.url.indexOf('?') === -1) ? '?' : '&'; 
      config.url += orderedParams.join('&'); 

      return config; 
     }, 
    }; 
}); 

Invoke со следующим:

$http({ 
    method: 'GET', 
    url: 'http://example.com/url/v1/endpoint', 
    params: { 
     a: 'aValue', 
     b: 'bValue', 
     c: 'cValue' 
    }, 
    paramOrder: ['c', 'a'] 
}); 

, чтобы получить строку запроса, начинающуюся с ключа c, а затем a. Параметры, не упомянутые в paramOrder, будут добавляться после упорядоченных параметров (в алфавитном порядке).

+0

Хороший звонок, мне это нравится. –

1

В итоге я создал рудиментарный перехватчик, чтобы сохранить «как заданный» порядок параметров. Этот перехватчик запускается, если конфигурация переменной keepParamsOrder установлена ​​на вызов $http.

в модуле конфигурации:

$httpProvider.interceptors.push(function() { 
    return { 
     'request': function(config) { 
      if (!config.keepParamsOrder || !config.params) { 
       return config; 
      } 

      var queryStrings = []; 
      for (var key in config.params) { 
       if (config.params.hasOwnProperty(key)) { 
        queryStrings.push(key + '=' + config.params[key]); 
       } 
      } 

      // Reset the params to be empty 
      config.params = {}; 

      config.url += (config.url.indexOf('?') === -1) ? '?' : '&'; 
      config.url += queryStrings.join('&'); 

      return config; 
     }, 
    }; 
}); 

вещайте работать в конфигурации службы вызова:

this.apiCall = function() { 
    return $http({ 
     method: 'GET', 
     url: 'http://example.com/url/v1/endpoint', 
     params: { 
      'c': 'cdata', 
      'a': 'adata', 
      'b': 'bdata' 
     }, 
     keepParamsOrder: true 
    }); 
}; 
+0

Ваше решение как-то не хватает, поскольку вы все еще передаете 'params' в объект, который является [неупорядоченной коллекцией] (http://stackoverflow.com/questions/5525795/does-javascript-guarantee-object-property -заказ). Вместо добавления 'keepParamsOrder' вы можете либо распознать специальный синтаксис' params' (с участием 'Array'), либо добавить конфигурацию paramOrder, содержащую имена' params', которые вы хотите упорядочить. – hon2a

Смежные вопросы