发送HTTP请求
Egret 中封装了 XMLHttpRequest 进行异步的数据交互。
1.HTTP请求
通过 HTTP 协议可以实现 HTTP 客户端(如web浏览器)向 HTTP 服务端请求信息和服务。目前的 HTTP 1.1 协议是一种无状态协议,也就是说 HTTP 客户端和 HTTP 服务端不能保持持久的链接,使用请求/应答的模式来工作,如果客户端向服务端发送信息,服务端做出应答之后将关闭链接,来形成一套请求和应答。
1.1.基本过程
HTTP 通信机制都要经过如下的几个步骤:
- 建立TCP连接.
- Web浏览器向Web服务器发送请求命令.
- Web浏览器发送请求头信息
- Web服务器应答
- Web服务器发送应答头信息
- Web服务器向浏览器发送数据
- Web服务器关闭TCP连接(如果请求头部设置了Connection:keep-alive将保持连接状态仍然打开).
1.2.HTTP 请求方法
GET 方法
GET 方法是 HTTP 请求的默认方法,数据经过简单的编码发送出去,并作为 URL 的一部分发送到服务器。由于浏览器对 URL 长度的限制,提交的数据长度也有限制。
POST 方法
POST 方法克服了 GET 方法的一些缺点,可以发送较大的数据.数据也不再是明文发送的。出于安全的考虑一般选用 POST 方法。 POST 提交的数据也可以从标准输入输出流中获取。
2.发送请求
测试发送请求,需要一个稳定的服务端。可以使用httpbin.org提供的http://httpbin.org/get和http://httpbin.org/post这两个稳定的服务器地址来测试发送请求。其中get会返回 GET 请求的数据,post会返回 POST 请求发送的数据。
Egret 使用 HttpRequest 类发送 HTTP 请求。可以指定请求的方法为 GET 或者 POST 。可以通过监听加载事件来检测服务器端的响应。使用 HttpRequest 来发送请求的过程如下:
- 实例化一个 HttpRequest对象。
- 设置它的响应类型 responseType。
- 通过 open方法初始化请求一个对象,初始化请求地址和请求类型。
- 通过 setRequestHeader设置请求头信息。如果是POST带参数的请求这一步很重要,需要告诉服务端请求的参数格式,而且这一步需要在open之后执行。
- 通过 send方法发送请求,如果是post方法可以传入参数。
- 添加监听,监听服务器端的响应,包括进度事件和请求成功和失败事件。
代码如下:
const request =  new  egret.HttpRequest();
request.responseType  = egret.HttpResponseType.TEXT;
request.open("http://httpbin.org/get", egret.HttpMethod.GET);
request.setRequestHeader("Content-Type",  "application/x-www-form-urlencoded");
request.send();
request.addEventListener(egret.Event.COMPLETE,  this.onGetComplete,  this);
request.addEventListener(egret.IOErrorEvent.IO_ERROR,  this.onGetIOError,  this);
request.addEventListener(egret.ProgressEvent.PROGRESS,  this.onGetProgress,  this);
上面发送了一个 GET 请求到http://httpbin.org/get,然后添加回调事件,当请求成功或者失败之后来获取数据。
通过COMPLETE事件的response属性可获取到返回的信息。通过 ProgressEvent 事件的bytesLoaded和bytesTotal获取可加载进度。回调函数代码如下:
private  function  onGetComplete(event: egret.Event):  void  {
    const request =  <egret.HttpRequest\>event.currentTarget;
    console.log("get data : ", request.response);
    const responseLabel =  new  egret.TextField();
    responseLabel.size  =  18;
    responseLabel.text  =  "GET response: \n"  + request.response.substring(0,  50)  +  "...";
    this.addChild(responseLabel);
    responseLabel.x  =  50;
    responseLabel.y  =  70;
}
private  function  onGetIOError(event: egret.IOErrorEvent):  void  {
  console.log("get error : "  + event);
}
private  function  onGetProgress(event: egret.ProgressEvent):  void  {
  console.log("get progress : "  +  Math.floor(100  * event.bytesLoaded  / event.bytesTotal)  +  "%");
}
发送 POST 请求的代码如下:
const request =  new  egret.HttpRequest();
request.responseType  = egret.HttpResponseType.TEXT;
//设置为 POST 请求
request.open("http://httpbin.org/post", egret.HttpMethod.POST);
request.setRequestHeader("Content-Type",  "application/x-www-form-urlencoded");
request.send();
request.addEventListener(egret.Event.COMPLETE,  this.onPostComplete,  this);
request.addEventListener(egret.IOErrorEvent.IO_ERROR,  this.onPostIOError,  this);
request.addEventListener(egret.ProgressEvent.PROGRESS,  this.onPostProgress,  this);
添加回调函数:
private  function  onPostComplete(event: egret.Event):  void  {
    const request =  <egret.HttpRequest\>event.currentTarget;
    console.log("post data : ", request.response);
    const responseLabel =  new  egret.TextField();
    responseLabel.size  =  18;
    responseLabel.text  =  "POST response:\n"  + request.response.substring(0,  50)  +  "...";
    this.addChild(responseLabel);
    responseLabel.x  =  300;
    responseLabel.y  =  70;
}
private  function  onPostIOError(event: egret.IOErrorEvent):  void  {
  console.log("post error : "  + event);
}
private  function  onPostProgress(event: egret.ProgressEvent):  void  {
  console.log("post progress : "  +  Math.floor(100  * event.bytesLoaded  / event.bytesTotal)  +  "%");
}
3.发送带参数的请求
上面我们发送了一段空的请求到服务端,实际使用过程中一般都需要发送带参数的请求到服务端。
发送数据的格式:在 HTTP 客户端发送的数据,一般以key和value的形式组成,多个数据之间用&相连。拼接之后形成如下的形式:
key1=value1&key2=valueP2
通过 GET 方法发送的参数会加到 URL 的后面拼接起来,并以?分隔。POST 方法发送的参数需要先设置 HTTP 请求的头信息,告诉服务端是以什么样的形式来发送的数据。我们最常用的就是application/x-www-form-urlencoded,表示我们以key和value方式来格式化参数。服务端也可以用同样的方法来取到参数。
3.1.服务端获取参数配置
下面以 PHP 为例来简要说明发送和或取参数的基本过程。
PHP 环境配置请自行配置。其他后端语言同理。如果不使用
key和value的方式获取数据,请参考相应语言的标准输入流的方式来获取。
首先建立get_testphp文件,在 PHP 中获得 GET 的参数可以通过一个全局数组$_GET[]来获取到。下面代码将获取并返回key为p1和p2的参数的值。
<?php
  echo  $_GET['p1'];
  echo  $_GET['p2'];
?>
同理建立post_test.php,在 PHP 中通过全局数组$_POST[]来获取参数。下面代码将获取并返回key为p1和p2的参数的值。
<?php
  echo  $_POST['p1'];
  echo  $_POST['p2'];
?>
3.2.客户端发送参数
建立好两个 PHP 文件后,向他们发送参数。
首先是 GET 请求,GET 请求需要将参数拼接到 URL 后面实现。其中 URL 和 参数之间需要用 ? 链接。修改上面 GET 请求相应代码如下:
//拼接参数 
const params =  "?p1=getP1&p2=getP2";
const request =  new  egret.HttpRequest();
request.responseType  = egret.HttpResponseType.TEXT;
//将参数拼接到url
request.open("php/get_test.php"  + params, egret.HttpMethod.GET);
request.send();
发送 POST 请求. 需要注意的是发送 POST 请求需要将参数放到send方法的参数中发送出去。并且要设置其响应头,在我们的例子中使用key value 的方式来格式化参数,这里需要设置响应头Content-Type为application/x-www-form-urlencoded。修改上面 POST 请求相应代码如下:
//拼接参数
const params =  "p1=postP1&p2=postP2";
const request =  new  egret.HttpRequest();
request.responseType  = egret.HttpResponseType.TEXT;
request.open("php/post_test.php", egret.HttpMethod.POST);
//设置响应头
request.setRequestHeader("Content-Type",  "application/x-www-form-urlencoded");
//发送参数
request.send(params);
完整代码如下:
/*
 * 下面的示例使用 egret.HttpRequest 类进行网络通信。
 */
class  Main  extends  egret.DisplayObjectContainer  {
    private statusGetLabel: egret.TextField;
    private statusPostLabel: egret.TextField;
    public  constructor()  {
        super();
        this.sendGetRequest();
        this.sendPostRequest();
    }
    private  sendGetRequest():  void  {
        const statusGetLabel =  new  egret.TextField();
        this.statusGetLabel  = statusGetLabel;
        statusGetLabel.size  =  18;
        statusGetLabel.text  =  "GET request being sent to httpbin.org";
        this.addChild(statusGetLabel);
        statusGetLabel.x  =  50;
        statusGetLabel.y  =  40;
        const params =  "?p1=getP1&p2=getP2";
        const request =  new  egret.HttpRequest();
        request.responseType  = egret.HttpResponseType.TEXT;
        request.open("php/get_test.php"  + params, egret.HttpMethod.GET);
        request.send();
        request.addEventListener(egret.Event.COMPLETE,  this.onGetComplete,  this);
        request.addEventListener(egret.IOErrorEvent.IO_ERROR,  this.onGetIOError,  this);
        request.addEventListener(egret.ProgressEvent.PROGRESS,  this.onGetProgress,  this);
    }
    private  onGetComplete(event: egret.Event):  void  {
        const request =  <egret.HttpRequest\>event.currentTarget;
        console.log("get data : ", request.response);
        const responseLabel =  new  egret.TextField();
        responseLabel.size  =  18;
        responseLabel.text  =  "GET response: \n"  + request.response.substring(0,  50)  +  "...";
        this.addChild(responseLabel);
        responseLabel.x  =  50;
        responseLabel.y  =  70;
        this.statusGetLabel.text  =  "Get GET response!";
    }
    private  onGetIOError(event: egret.IOErrorEvent):  void  {
    
    }
    private  onGetProgress(event: egret.ProgressEvent):  void  {
        console.log("get progress : "  +  Math.floor(100  * event.bytesLoaded  / event.bytesTotal)  +  "%");
    }
    private  sendPostRequest()  {
        const statusPostLabel =  new  egret.TextField();
        this.statusPostLabel  = statusPostLabel;
        this.addChild(statusPostLabel);
        statusPostLabel.size  =  18;
        statusPostLabel.x  =  300;
        statusPostLabel.y  =  40;
        statusPostLabel.text  =  "Sending POST request to httpbin.org";
        const params =  "p1=postP1&p2=postP2";
        const request =  new  egret.HttpRequest();
        request.responseType  = egret.HttpResponseType.TEXT;
        request.open("php/post_test.php", egret.HttpMethod.POST);
        request.setRequestHeader("Content-Type",  "application/x-www-form-urlencoded");
        request.send(params);
        request.addEventListener(egret.Event.COMPLETE,  this.onPostComplete,  this);
        request.addEventListener(egret.IOErrorEvent.IO_ERROR,  this.onPostIOError,  this);
        request.addEventListener(egret.ProgressEvent.PROGRESS,  this.onPostProgress,  this);
    }
    private  onPostComplete(event: egret.Event)  {
        const request =  <egret.HttpRequest\>event.currentTarget;
        console.log("post data : ", request.response);
        const responseLabel =  new  egret.TextField();
        responseLabel.size  =  18;
        responseLabel.text  =  "POST response:\n"  + request.response.substring(0,  50)  +  "...";
        this.addChild(responseLabel);
        responseLabel.x  =  300;
        responseLabel.y  =  70;
        this.statusPostLabel.text  =  "Get POST response!";
    }
    private  onPostIOError(event: egret.IOErrorEvent):  void  {
        console.log("post error : "  + event);
    }
    private  onPostProgress(event: egret.ProgressEvent):  void  {
        console.log("post progress : "  +  Math.floor(100  * event.bytesLoaded  / event.bytesTotal)  +  "%");
    }
}

