【问题标题】:How to intercept convenience shortcuts of $http in AngularJS如何在 AngularJS 中拦截 $http 的便捷快捷方式
【发布时间】:2019-03-03 22:28:03
【问题描述】:

我有以下函数 (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;
 }]);

【问题讨论】:

    标签: angularjs cordova decorator angular-decorator


    【解决方案1】:

    这是我最终得出的一个可行的解决方案。

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

    【讨论】:

      【解决方案2】:

      如果我正确理解您的意图,您分配挂起 wrapper 的 HTTP 方法的方式不会调用您的 wrapper 函数的内容。

      请注意,$http 便利函数的参数会有所不同。

      例子:

      • GET 描述为:get(url, [config])
      • POST 描述为:post(url, data, [config])

      考虑到上述情况,当使用 $http 便利方法时,这是一种委托给您的 wrapper 函数的方法,该函数在 XHR 和 Cordova 插件之间切换:

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

      【讨论】:

      • 非常感谢。我的问题是 $http ({method:'...') 调用被我的代码捕获,而不是 $http.get/post/etc。您的答案看起来比我发布问题后得出的解决方案更简洁。我会发布我重新设计的解决方案作为替代答案,但下周也会尝试你的 - 它看起来更优雅。
      猜你喜欢
      • 1970-01-01
      • 2011-04-08
      • 1970-01-01
      • 1970-01-01
      • 2019-04-29
      • 1970-01-01
      • 2016-08-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多