zoukankan      html  css  js  c++  java
  • Make AngularJS $http service behave like jQuery.ajax()(转)

    There is much confusion among newcomers to AngularJS as to why the $http service shorthand functions ($http.post(), etc.) don’t appear to be swappable with the jQuery equivalents (jQuery.post(), etc.) even though the respective manuals imply identical usage. That is, if your jQuery code looked like this before:

    (function($) {
      jQuery.post('/endpoint', { foo: 'bar' }).success(function(response) {
        // ...
      });
    })(jQuery);

    You may find that the following doesn’t exactly work for you with AngularJS out of the box:

    var MainCtrl = function($scope, $http) {
      $http.post('/endpoint', { foo: 'bar' }).success(function(response) {
        // ...
      });
    };

    The problem you may encounter is that your server does not appear to receive the { foo: 'bar' } params from the AngularJS request.

    The difference is in how jQuery and AngularJS serialize and transmit the data. Fundamentally, the problem lies with your server language of choice being unable to understand AngularJS’s transmission natively—that’s a darn shame because AngularJS is certainly not doing anything wrong. By default, jQuery transmits data usingContent-Type: x-www-form-urlencoded and the familiar foo=bar&baz=moe serialization. AngularJS, however, transmits data using Content-Type: application/json and { "foo": "bar", "baz": "moe" } JSON serialization, which unfortunately some Web server languages—notably PHP—do not unserialize natively.

    Thankfully, the thoughtful AngularJS developers provided hooks into the $http service to let us impose x-www-form-urlencoded on all our transmissions. There are many solutions people have offered thus far on forums and StackOverflow, but they are not ideal because they require you to modify either your server code or your desired usage pattern of $http. Thus, I present to you the best possible solution, which requires you to change neither server nor client code but rather make some minor adjustments to $http‘s behavior in the config of your app’s AngularJS module:

    // Your app's root module...
    angular.module('MyModule', [], function($httpProvider) {
      // Use x-www-form-urlencoded Content-Type
      $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
    
      /**
       * The workhorse; converts an object to x-www-form-urlencoded serialization.
       * @param {Object} obj
       * @return {String}
       */ 
      var param = function(obj) {
        var query = '', name, value, fullSubName, subName, subValue, innerObj, i;
          
        for(name in obj) {
          value = obj[name];
            
          if(value instanceof Array) {
            for(i=0; i<value.length; ++i) {
              subValue = value[i];
              fullSubName = name + '[' + i + ']';
              innerObj = {};
              innerObj[fullSubName] = subValue;
              query += param(innerObj) + '&';
            }
          }
          else if(value instanceof Object) {
            for(subName in value) {
              subValue = value[subName];
              fullSubName = name + '[' + subName + ']';
              innerObj = {};
              innerObj[fullSubName] = subValue;
              query += param(innerObj) + '&';
            }
          }
          else if(value !== undefined && value !== null)
            query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&';
        }
          
        return query.length ? query.substr(0, query.length - 1) : query;
      };
    
      // Override $http service's default transformRequest
      $httpProvider.defaults.transformRequest = [function(data) {
        return angular.isObject(data) && String(data) !== '[object File]' ? param(data) : data;
      }];
    });

    Do not use jQuery.param() in place of the above homegrown param() function; it will cause havoc when you try to use AngularJS $resourcebecause jQuery.param() will fire every method on the $resource class passed to it! (This is a feature of jQuery whereby function members of the object to parametrize are called and the return values are used as the parametrized values, but for our typical use case in AngularJS it is detrimental since we typically pass “real” object instances with methods, etc.)

    Now you can go forward with using $http.post() and other such methods as you would expect with existing server code that expects x-www-form-urlencodeddata. Here are a few sample frames of the final result for your day-to-day, end-to-end code (i.e. what you hoped and dreamed for):

    The HTML template

    <div ng-app="MyModule" ng-controller="MainCtrl">
      <p ng-show="loading">Loading...</p>
      <p ng-hide="loading">Response: {{response}}</p>
    </div>

    The client code (AngularJS)

    var MainCtrl = function($scope, $http) {
      $scope.loading = true;
      $http.post('/endpoint', { foo: 'bar' }).success(function(response) {
        $scope.response = response;
        $scope.loading = false;
      });
    };

    The server code (PHP)

    <?
    header('Content-Type: application/json');
    
    // Ta-da, using $_POST as normal; PHP is able to
    // unserialize the AngularJS request no problem
    echo json_encode($_POST);
    ?>

    Other notes

    So you may wonder now, is it possible for PHP to read the JSON request from stock AngularJS? Why, of course, by reading the input to PHP and JSON decoding it:

    <?
    $params = json_decode(file_get_contents('php://input'));
    ?>

    Obviously the downside to this is that the code is a little less intuitive (we’re used to $_POST, after all), and if your server-side handlers are already written to rely on$_POST, you will now have to change server code. If you have a good framework in place, you can probably effect a global change such that your input reader will transparently detect JSON requests, but I digress.

    Thank you for reading. I hope you enjoyed my first POST. (Get it?!)

  • 相关阅读:
    读写excel的组件
    一个关于C#语言中的Property的低级BUG,花了我二十分钟
    使用wwAppConfiguration类库来轻松读写应用程序配置信息
    为因地震死难的同胞默哀
    页面执行时生成静态文件的方法
    【转载】sp_spaceused2,看库里全部表占用的物理空间
    在微软中文技术论坛 CSDN cnblogs 三个微软社区中提问
    在内网服务器中获得真正的客户端ip的方法
    深拷贝的通用方法
    你知道在word中如何将段落标记替换成其他字符吗?
  • 原文地址:https://www.cnblogs.com/hubing/p/4588224.html
Copyright © 2011-2022 走看看