Heim  >  Artikel  >  php教程  >  Lösung für das Problem, dass der asynchrone Hintergrund von $http keine Anforderungsparameter in AngularJS abrufen kann

Lösung für das Problem, dass der asynchrone Hintergrund von $http keine Anforderungsparameter in AngularJS abrufen kann

高洛峰
高洛峰Original
2016-12-08 09:48:331509Durchsuche

Das Beispiel in diesem Artikel beschreibt die Lösung des Problems, dass der asynchrone Hintergrund von $http die Anforderungsparameter in AngularJS nicht abrufen kann. Teilen Sie es als Referenz mit allen. Die Details lauten wie folgt:

Angular verwendet bei der asynchronen Übermittlung von Daten einen anderen Anforderungsheader und eine andere Datenserialisierungsmethode als jQuery, was dazu führt, dass einige Hintergrundprogramme die Daten nicht normal analysieren können.

Prinzipielle Analyse (Online-Analyse):

Für AJAX-Anwendungen (mit XMLHttpRequests) ist die herkömmliche Methode zum Initiieren einer Anfrage an den Server: Erhalten Sie einen Verweis auf ein XMLHttpRequest-Objekt und initiieren Sie eine Anfrage , lesen Sie „Antwort abrufen“, überprüfen Sie den Statuscode und verarbeiten Sie schließlich die Antwort vom Server. Ein Beispiel für den gesamten Prozess ist wie folgt:

var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
  if(xmlhttp.readystate == 4 && xmlhttp.status == 200) {
    var response = xmlhttp.responseText;
  }else if(xmlhttp.status == 400) { //或者可以是任何以4开头的状态码
    //优雅地处理错误
  }
};
//建立连接
xmlhttp.open("GET", "http://myserver/api", true);
//发起请求
xmlhttp.send();


Dies ist eine sehr umständliche Aufgabe für einfache, häufige und häufig wiederholte Aufgaben. Wenn Sie den oben genannten Prozess wiederverwenden möchten, sollten Sie ihn kapseln oder eine Codebibliothek verwenden.

Die AngularJS XHR API folgt einer Schnittstelle, die allgemein als Promise bekannt ist. Da es sich bei XHR um eine asynchrone Aufrufmethode handelt, wird die Antwort des Servers zu einem ungewissen Zeitpunkt in der Zukunft zurückgegeben (wir hoffen, dass sie sofort zurückgegeben wird). Die Promise-Schnittstelle gibt an, wie mit dieser Antwort umgegangen wird, und ermöglicht Benutzern von Promise, sie auf vorhersehbare Weise zu verwenden.

Zum Beispiel möchten wir die Informationen eines Benutzers vom Server erhalten. Angenommen, die Hintergrundschnittstelle, die zum Akzeptieren von Anforderungen verwendet wird, befindet sich im Pfad /api/user. Diese Schnittstelle kann ein ID-Attribut als URL-Parameter akzeptieren , und verwenden Sie dann Angulars. Ein Beispiel dafür, wie der Kerndienst $http eine Als Benutzer sollten Sie feststellen, dass AngularJS und jQuery in der Handhabung asynchroner Anforderungen sehr ähnlich sind.

$http.get('api/user', {params: {id:'5'}
}).success(function(data, status, headers, config) {
  //加载成功之后做一些事
}).error(function(data, status, headers, config) {
  //处理错误
});
Die im obigen Beispiel verwendete Methode $http.get ist eine der vielen Verknüpfungsmethoden, die vom Kerndienst $http von AngularJS bereitgestellt werden. Wenn Sie AngularJS verwenden möchten, um eine POST-Anfrage mit einigen POST-Daten an dieselbe URL zu senden, können Sie dies folgendermaßen tun:


Es gibt ähnliche Verknüpfungsmethoden für die am häufigsten verwendeten Anforderungstypen, einschließlich: GET, HEAD, POST, DELETE, PUT, JSONP.

var postData = {text:'long blob of text'};
//下面这一行会被当成参数附加到URL后面,所以post请求最终会变成/api/user?id=5
var config = {params: {id: '5'}};
$http.post('api/user', postData, config
).success(function(data, status, headers, config) {
  //成功之后做一些事情
}).error(function(data, status, headers, config) {
  //处理错误
});
1. Konfigurieren Sie die Anfrage weiter

Obwohl die Standard-Anfragemethode relativ einfach zu verwenden ist, hat sie manchmal den Nachteil einer schlechten Konfigurierbarkeit. Sie werden auf Schwierigkeiten stoßen, wenn Sie die folgenden Dinge implementieren möchten:


a. Fügen Sie der Anfrage einige Autorisierungsheader hinzu.

b. Ändern Sie die Art und Weise, wie mit dem Cache umgegangen wird.

c. Verwenden Sie einige spezielle Methoden, um die gesendete Anfrage oder die empfangene Antwort umzuwandeln.

In diesen Fällen können Sie die Anfrage umfassend konfigurieren, indem Sie ihr ein optionales Konfigurationsobjekt übergeben. Im vorherigen Beispiel haben wir mithilfe des Konfigurationsobjekts einen optionalen URL-Parameter angegeben. Bei den Methoden GET und POST gibt es jedoch einige Abkürzungen. Ein Beispiel für einen Methodenaufruf nach dieser tiefgreifenden Vereinfachung lautet wie folgt:



Das Folgende ist eine grundlegende Pseudocode-Vorlage zum Aufrufen der vorherigen Methode :

$http(config)


GET, POST und andere Verknüpfungsmethoden legen automatisch Methodenparameter fest, sodass keine Notwendigkeit besteht, sie manuell festzulegen. Das Konfigurationsobjekt wird als letzter Parameter an $http.get und $http.post übergeben, sodass dieser Parameter in allen Verknüpfungsmethoden verwendet werden kann. Sie können ein Konfigurationsobjekt übergeben, um die gesendete Anfrage zu ändern. Das Konfigurationsobjekt kann die folgenden Schlüsselwerte festlegen.

$http({
  method: string,
  url: string,
  params: object,
  data: string or object,
  headers: object,
  transformRequest: function transform(data, headersGetter) or an array of functions,
  transformResponse: function transform(data, headersGetter) or an array of functions,
  cache: boolean or Cache object,
  timeout: number,
  withCredentials: boolean
});
Methode: eine Zeichenfolge, die den Typ der HTTP-Anfrage angibt, z. B. GET oder POST.

URL: URL-Zeichenfolge, die den angeforderten absoluten oder relativen Ressourcenpfad angibt.

params: Ein Objekt, dessen Schlüssel und Werte beide Zeichenfolgen sind (genauer gesagt eine Karte), die die Schlüssel und Werte darstellen, die in URL-Parameter konvertiert werden müssen. Beispiel:




wird in

[{key1: 'value1', key2: 'value2'}]


und wird an die URL angehängt. Wenn wir ein js-Objekt (anstelle einer Zeichenfolge oder eines numerischen Werts) als Wert in der Karte verwenden, wird das js-Objekt in eine JSON-Zeichenfolge konvertiert.

Daten: eine Zeichenfolge oder ein Objekt, das als Anforderungsdaten gesendet wird.
?key1=value&key2=value2
Timeout: Die Anzahl der Millisekunden, die gewartet werden muss, bevor die Anforderung abläuft.

2. HTTP-Header festlegen


AngularJS verfügt über einige Standard-Anfrageheader, und alle von Angular ausgegebenen Anfragen verfügen über diese Standard-Anfrageheader. Die Standardanforderungsheader umfassen die folgenden zwei:

1.Accept:application/json,text/pain,/

2.X-Requested-With: XMLHttpRequest


Wenn Sie möchten Das Festlegen eines speziellen Anforderungsheaders kann in den folgenden zwei Methoden implementiert werden.

Die erste Methode: Wenn Sie den Anforderungsheader für jede gesendete Anforderung festlegen möchten, können Sie den zu verwendenden speziellen Anforderungsheader auf den Standardwert von AngularJS festlegen. Diese Werte können über das Konfigurationsobjekt $httpProvider.defaults.headers festgelegt werden, normalerweise im Konfigurationsabschnitt der Anwendung. Wenn Sie also den „DO NOT TRACK“-Header für alle GET-Anfragen verwenden und den Requested-With-Header für alle Anfragen entfernen möchten, können Sie einfach Folgendes tun:


如果你只想对某些特定的请求设置请求头,但不把它们作为默认值,那么你可以把头信息作为配置对象的一部分传递给$http服务。同样的,自定义头信息也可以作为第二个参数的一部分传递给GET请求,第二个参数还可以同时接受URL参数。

$http.get('api/user', {
   //设置Authorization(授权)头。在真实的应用中,你需要到一个服务里面去获取auth令牌
   headers: {'Authorization': 'Basic Qzsda231231'},
   params: {id:5}
}).success(function() {//处理成功的情况 });

   


三.缓存响应

对于HTTP GET请求,AngularJS提供了一个开箱即用的简单缓存机制。默认情况下它对所有请求类型都不可用,为了启用缓存,你需要做一些配置:

$http.get('http://server/myapi', {
  cache: true
}).success(function() {//处理成功的情况});

   


这样就可以启用缓存,然后AngularJS将会缓存来自服务器的响应。下一次向同一个URL发送请求的时候,AngularJS将会返回缓存中的响应内容。缓存也是智能的,所以即使你向同一个URL发送多次模拟的请求,缓存也只会向服务器发送一个请求,而且在收到服务端的响应之后,响应的内容会被分发给所有请求。

但是,这样做有些不太实用,因为用户会先看到缓存的旧结果,然后看到新的结果突然出现。例如,当用户即将点击一条数据时,它可能会突然发生变化。

注意,从本质上来说,响应(即使是从缓存中读取的)依然是异步的。换句话说,在第一次发出请求的时候,你应该使用处理异步请求的方式来编码。

四.转换请求和响应

对于所有通过$http服务发出的请求和收到的响应来说,AngularJS都会进行一些基本的转换,包括如下内容。

1.转换请求

如果请求的配置对象属性中包含JS对象,那么就把这个对象序列化成JSON格式。

2.转换响应

如果检测到了XSRF(Cross Site Request Forgery的缩写,意为跨站请求伪造,这是跨站脚本攻击的一种方式)前缀,则直接丢弃。如果检测到了JSON响应,则使用JSON解析器对它进行反序列化。

如果你不需要其中的某些转换,或者想自已进行转换,可以在配置项里面传入自已的函数。这些函数会获取HTTP的request/response体以及协议头信息,然后输出序列化、修改之后的版本。可以使用transformLRequest和transformResponse作为key来配置这些转换函数,而这两个函数在模块的config函数中是用$httpProvider服务来配置的。

我们什么时候需要使用这些东西呢?假设我们有一个服务,它更适合用jQuery的方式来操作。POST数据使用key1=val1&key2=val2(也就是字符串)形式来代替{key1:val1, key2:val2}JSON格式。我们可以在每个请求中来进行这种转换,也可以添加一个独立transformRequest调用,对于当前这个例子来说,我们打算添加一个通用的transformRequest,这样所有发出的请求都会进行这种从JSON到字符串的转换。下面就是实现方式:

var module = angular.module('myApp');
module.config(function($httpProvider) {
  $httpProvider.defaults.transformRequest = function(data) {
     //使用jQuery的param方法把JSON数据转换成字符串形式
     return $.param(data);
   };
});

   


实列配置:

在使用中发现后台程序还是无法解析angular提交的数据,对比后发现头部缺少‘X-Requested-With'项

所以在配置中加入:

复制代码代码如下:

$httpProvider.defaults.headers.post['X-Requested-With'] = 'XMLHttpRequest'


下面贴入测试时的部分配置代码:

angular.module('app', [
  'ngAnimate',
  'ngCookies',
  'ngResource',
  'ngRoute',
  'ngSanitize',
  'ngTouch'
],function ($httpProvider) {
  // 头部配置
  $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
  $httpProvider.defaults.headers.post['Accept'] = 'application/json, text/javascript, */*; q=0.01';
  $httpProvider.defaults.headers.post['X-Requested-With'] = 'XMLHttpRequest';
  /**
   * 重写angular的param方法,使angular使用jquery一样的数据序列化方式 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 + &#39;[&#39; + i + &#39;]&#39;;
          innerObj = {};
          innerObj[fullSubName] = subValue;
          query += param(innerObj) + &#39;&&#39;;
        }
      }
      else if (value instanceof Object) {
        for (subName in value) {
          subValue = value[subName];
          fullSubName = name + &#39;[&#39; + subName + &#39;]&#39;;
          innerObj = {};
          innerObj[fullSubName] = subValue;
          query += param(innerObj) + &#39;&&#39;;
        }
      }
      else if (value !== undefined && value !== null)
        query += encodeURIComponent(name) + &#39;=&#39; + encodeURIComponent(value) + &#39;&&#39;;
    }
    return query.length ? query.substr(0, query.length - 1) : query;
  };
  // Override $http service&#39;s default transformRequest
  $httpProvider.defaults.transformRequest = [function (data) {
    return angular.isObject(data) && String(data) !== &#39;[object File]&#39; ? param(data) : data;
  }];
}).config(function ($routeProvider) {
    $routeProvider
      .when(&#39;/&#39;, {
        templateUrl: &#39;views/main.html&#39;,
        controller: &#39;MainCtrl&#39;
      })
      .when(&#39;/about&#39;, {
        templateUrl: &#39;views/about.html&#39;,
        controller: &#39;AboutCtrl&#39;
      })
      .otherwise({
        redirectTo: &#39;/&#39;
      });
  });

   


希望本文所述对大家AngularJS程序设计有所帮助。


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn