Как перехватить удобные ярлыки $ http в AngularJS - PullRequest
0 голосов
/ 28 сентября 2018

У меня есть следующая функция ( credit ), которая оборачивает функцию AngularJS $http таким образом, что она вызывает браузер XHR при работе на рабочем столе, но вызывает cordova-plugin-advanced-http, если на мобильном телефоне.

Кажется, что это работает, когда я использую $http({method:'get/post'}...), но не работает, если я вызываю удобные ярлыки, такие как $http.get(...)

Может кто-нибудь предложить, какие изменения мне нужно сделать?

 $provide.decorator('$http', ['$delegate', '$q', function($delegate, $q) {
      // create function which overrides $http function
      var $http = $delegate;

      var wrapper = function () {

        var url = arguments[0].url;
        var method = arguments[0].method;
        var isOutgoingRequest = /^(http|https):\/\//.test(url);


        if (window.cordova && isOutgoingRequest) {
          console.log ("**** -->"+method+"<-- using native HTTP with:"+url);

          var d = $q.defer();

          var options = {
            method: method,
            data: arguments[0].data,
            headers: arguments[0].headers,
            timeout: arguments[0].timeout

          };


           cordova.plugin.http.sendRequest(url,options,
            function (succ) {
              console.log ("***  Inside native HTTP success with:"+JSON.stringify(succ));

              try {


                if (options.headers && options.headers['x-parse']=='text')
                    d.resolve({"data":succ.data});
                else 
                d.resolve({"data":JSON.parse(succ.data)});
                return d.promise;

              }
              catch (e) {
                d.resolve({"data":succ.data});
                return d.promise;
              }

            }, 
            function (err) {
              console.log ("***  Inside native HTTP error");
              d.reject(err);
              return d.promise;
            });
            return d.promise;

        }
        else {
          console.log ("**** "+method+" using XHR HTTP for "+url);
          return $http.apply($http, arguments);
        }


      };


      Object.keys($http).filter(function (key) {
        return (typeof $http[key] === 'function');
      }).forEach(function (key) {
        wrapper[key] = function () {

          // Apply global changes to arguments, or perform other
          // nefarious acts.

         // console.log ("KEY="+key);

          return $http[key].apply($http, arguments);
        };
      });

      return wrapper;
 }]);

Ответы [ 2 ]

0 голосов
/ 29 сентября 2018

Вот рабочее решение, к которому я в конце концов пришел.

// Wraps around $http that switches between browser XHR
// or cordova-advanced-http based on if cordova is available 
// credits:
// a) https://www.exratione.com/2013/08/angularjs-wrapping-http-for-fun-and-profit/
// b) https://gist.github.com/adamreisnz/354364e2a58786e2be71

$provide.decorator('$http', ['$delegate', '$q', function($delegate, $q) {
  // create function which overrides $http function
  var $http = $delegate;

  var wrapper = function () {
    var url;
    var method;

     url = arguments[0].url;
     method = arguments[0].method;
    var isOutgoingRequest = /^(http|https):\/\//.test(url);
    if (window.cordova && isOutgoingRequest) {
      console.log ("**** -->"+method+"<-- using native HTTP with:"+encodeURI(url));
      var d = $q.defer();
      var options = {
        method: method,
        data: arguments[0].data,
        headers: arguments[0].headers,
        timeout: arguments[0].timeout,
        responseType: arguments[0].responseType
      };

       cordova.plugin.http.sendRequest(encodeURI(url),options,
        function (succ) {
          // automatic JSON parse if no responseType: text
          // fall back to text if JSON parse fails too
          if (options.responseType =='text') {
            // don't parse into JSON
            d.resolve({"data":succ.data});
            return d.promise;
          }
          else {
            try {
              d.resolve({"data":JSON.parse(succ.data)});
              return d.promise;
            }
            catch (e) {

              console.log ("*** Native HTTP response: JSON parsing failed for "+url+", returning text");
              d.resolve({"data":succ.data});
              return d.promise;
            }

          }
        }, 
        function (err) {
          console.log ("***  Inside native HTTP error: "+JSON.stringify(err));
          d.reject(err);
          return d.promise;
        });
        return d.promise;

    }
    else { // not cordova, so lets go back to default http
      console.log ("**** "+method+" using XHR HTTP for "+url);
      return $http.apply($http, arguments);
    }

  };

  // wrap around all HTTP methods
  Object.keys($http).filter(function (key) {
    return (typeof $http[key] === 'function');
  }).forEach(function (key) {
    wrapper[key] = function () {
      return $http[key].apply($http, arguments);
    };
  });
// wrap convenience functions
  $delegate.get = function (url,config) {
    return wrapper(angular.extend(config || {}, {
      method: 'get',
      url: url
    }));
  };

  $delegate.post = function (url,data,config) {
    return wrapper(angular.extend(config || {}, {
      method: 'post',
      url: url,
      data:data
    }));
  };

  $delegate.delete = function (url,config) {
    return wrapper(angular.extend(config || {}, {
      method: 'delete',
      url: url
    }));
  };

  return wrapper;
}]);
0 голосов
/ 28 сентября 2018

Если я правильно понял ваше намерение, то, как вы назначаете методы HTTP, которые зависают wrapper, не вызовет содержимое вашей функции wrapper.

Обратите внимание, что параметры$http удобные функции различаются.

Примеры:

  • GET описывается как: get(url, [config])
  • POST описывается как: post(url, data, [config])

Учитывая вышесказанное, вот один из способов делегирования вашей функции wrapper, которая переключается между XHR и плагином Cordova при использовании удобных методов $http:

wrapper[key] = function () {
  var url = arguments[0];
  if (['get', 'delete', 'head', 'jsonp'].indexOf(key) !== -1) {
    // arguments[1] == config
    return wrapper(Object.assign({
      method: key,
      url: url,
    }, arguments[1]));
  } else {
    // POST, PUT, PATCH
    // arguments[1] == data
    // arguments[2] == config
    return wrapper(Object.assign({
      data: arguments[1],
      method: key,
      url: url,
    }, arguments[2]));
  }
};
...