CocosCreator中XMLHttpReques 网络数据请求

XMLHttpRequest 用于短连接, Web 平台上最广泛使用的标准网络接口,在IOS中 类似 AFNetworking 做IOS的应该知道。标准文档请参考 MDN 中文文档

初始化

  • 可以直接使用 new XMLHttpRequest() 来创建一个连接对象。
  • cc.loader.getXMLHttpRequest() 来创建。

使用
提交一个表单,它里面有两个字段,假如为 phone = 10086888888 和 password=1234`x。参数有特殊符号转换为ASCII HEX值。如果你用 POST 方法,那么服务器将会接收到一个字符串类似于下面三种情况之一,其中的区别依赖于你采用何种编码类型:

  • POST ,Content-Type 为 application/x-www-form-urlencoded 编码类型

    Content-Type: application/x-www-form-urlencoded
    phone=10086888888&password=1234%60x

  • POST ,Content-Type 为 text/plain 编码类型

    Content-Type: text/plain
    phone=10086888888
    password=1234%60x

  • POST ,Content-Type 为 multipart/form-data 编码类型
    multipart/form-data不会对参数编码,使用的boundary(分割线),相当于&,
    boundary的值是——–314911788813839

    Content-Type: multipart/form-data;
    ——–314911788813839
    Content-Disposition: form-data; name=”phone”
    10086888888&
    ——–314911788813839
    Content-Disposition: form-data; name=”password”
    1234%60x
    ——–314911788813839

  • 使用 GET 方法 请求Content-Type 属性会被忽略,像下面这样的字符串将被简单的附加到 URL

    ?phone=10086888888&password=1234%60x

XMLHttpRequest的基础使用在MDN web docs参考,

直接上代码。如果有问题可以下面评论留言交流。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
class XMLRequest{

constructor(){
//console.log('constructor');
this._token = null;
this._timeout = 10.0 * 1000; //10s 请求超时时间
}
/**
* get请求
* @param {*} url Url请求地址
* @param {*} params 请求参数
* @param {*} callback 数据回调
*/
get(url,params,callback){
this.logintoken(function(){
let requestUrl = cc.config.host_address + url + "?";
if(params){
params = this.queryStringFromParameters(params);
}
this.xhrRequest("GET",requestUrl,params,true,function(xhr){
if (xhr.readyState == 4 && (xhr.status >= 200 && xhr.status < 400)) {
var response = JSON.parse(xhr.responseText);
console.log(requestUrl + params + "\n\n"+ JSON.stringify(response));
if(response["code"] != 0){
cc.hud.show(1.5,response["msg"],undefined,function(){
}.bind(this));
}else{
var data = response["data"];
if(data && callback){
callback(data);
}
}
}
}.bind(this));
}.bind(this));
}

/**
* post请求
* @param {*} url Url请求地址
* @param {*} params 请求参数
* @param {*} callback 数据回调
*/
post(url,params,callback){
this.logintoken(function(){
let requestUrl = cc.config.host_address + url;
if(params){
params = this.queryStringFromParameters(params);
}
this.xhrRequest("POST",requestUrl,params,true,function(xhr){
if (xhr.readyState == 4 && (xhr.status >= 200 && xhr.status < 400)) {
var response = JSON.parse(xhr.responseText);
console.log(requestUrl + params + "\n\n"+ JSON.stringify(response));
if(response["code"] != 0){
cc.hud.show(1.5,response["msg"],undefined,function(){
}.bind(this));
}else{
var data = response["data"];
if(data && callback){
callback(data);
}
}
}
}.bind(this));
}.bind(this));
}

/**
* 初始化一个请求类
* @param {*} method "POST GET"
* @param {*} url 请求地址
* @param {*} params 请求的参数
* @param {*} async 是否移步
* @param {*} onreadystatechangeCallback 回调函数
*/
xhrRequest(method, url, params, async,onreadystatechangeCallback){
let xhr = new XMLHttpRequest();
xhr.timeout = this._timeout;
xhr.onreadystatechange = function () {
if(onreadystatechangeCallback){
onreadystatechangeCallback(xhr);
}
};
xhr.open(method, url, async);
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
if(cc.request._token){
xhr.setRequestHeader("token",cc.request._token);
}
xhr.withCredentials = true;
xhr.send(params);
}

/**
* 登录token
*/
logintoken(callback){
if(this._token == undefined ||this._token == null){
let requestUrl = cc.config.host_address + cc.config.login;
let params = {password: "123456",phone:"18888888888"};
var mutablePairs = this.queryStringFromParameters(params);
this.xhrRequest("POST",requestUrl,mutablePairs,true,function(xhr){
xhr.onreadystatechange = function(){
if (xhr.readyState == 4 && (xhr.status >= 200 && xhr.status < 400)) {
var response = JSON.parse(xhr.responseText);
cc.request._token = response["data"];
console.log("登录校验token " + cc.request._token);
if(callback){
callback();
}
}
};
}.bind(this));
}else{
if(callback){
callback();
}
}
}

/**
* 字典转拼接的字符串
*/
queryStringFromParameters(parameters){
var mutablePairs = "";
var res = Object.keys(parameters).sort();
for(var key in res){
let tempkey = res[key];
let value = parameters[res[key]];
if(Array.isArray(value)){
mutablePairs += tempkey + "=" + JSON.stringify(value) +"&";
}else{
mutablePairs += tempkey + "=" + value +"&";
}
}
if(mutablePairs.length > 1){
mutablePairs = mutablePairs.substr(0,mutablePairs.length-1);
mutablePairs = encodeURI(mutablePairs);
}
return mutablePairs;
}

/**
* Set the imageView `image` with an `url` and a placeholder.
* The download is asynchronous and cached.
* @param url The url for the image.
* @param placeholder The image to be set initially, until the image request finishes.
*/
setImageWithURL(sprite,url, placeholderImage){
let remoteUrl = url;
if(placeholderImage){
let pathURL = placeholderImage;
cc.loader.loadRes(pathURL, cc.SpriteFrame, function (err, sf) {
if(!err){
this.spriteFrame = sf;
}else{
console.log("error:"+err);
}
}.bind(sprite));
}
if(remoteUrl){
cc.loader.load(remoteUrl, function (err, texture) {
// Use texture to create sprite frame
if(!err){
this.spriteFrame = new cc.SpriteFrame(texture);
}else{
console.log("加载网络图片出错:"+ err);
}
}.bind(sprite));
}
}
}

/**
* get XMLRequest
* @returns {XMLRequest}
*/
var instance;
var getXMLRequest = function(){
if(!instance){
instance = new XMLRequest();
}
return instance;
}
module.exports = cc.request = getXMLRequest();

上面是对 XMLHttpRequest简单的封装

  • 网络数据调用:
    1
    2
    3
    4
    5
    6
    第一个参数为你接口路径地址,第二个为参数字典。

    cc.request.post(cc.config.question_getrandonequestion,null,function(response){
    this._data = response;
    this.setDataResponse(response);
    }.bind(this));
  • 远程图片Url调用:
    1
    cc.request.setImageWithURL(this.questionImg.getComponent(cc.Sprite),imgUrl);

creator.d.ts加载本地图片的两种方式

1
2
3
4
5
6
7
8
9
10
11
12
let pathURL = "singleColor";//这儿指必须在 resources 目标下的资源图片
cc.loader.loadRes(pathURL, cc.SpriteFrame, function (err, sf) {
if(!err){
this.hudNode.getComponent(cc.Sprite).spriteFrame = sf;
this.hudNode.color = cc.Color.BLACK;
this.hudNode.opacity = 230;
//透明度级联功能从 v2.0 开始已移除 节点的不透明度值是否影响其子节点,默认值为 true
//this.hudNode.cascadeOpacity = false;
}else{
console.log("error:"+err);
}
}.bind(this));

第二种加载出Texture 构造SpriteFrame ,Use texture to create sprite frame。

1
2
3
4
5
6
7
8
9
10
11
this.hudNode.spriteFrame = new cc.SpriteFrame(cc.textureCache.addImage(cc.url.raw(pathURL)));

等效

cc.loader.loadRes(pathURL, cc.SpriteFrame, function (err, sf) {
if(!err){
this.spriteFrame = sf;
}else{
console.log("error:"+err);
}
}.bind(sprite));

如果出现 同源策略禁止读取位于 ‘http://你的地址’ 的远程资源。(原因:凭据不支持,如果 CORS 头 ‘Access-Control-Allow-Origin’ 为 ‘*’)一般情况下

  • 请求的url是aspx页面,则需要在aspx页面中添加代码:Response.AddHeader(“Access-Control-Allow-Origin”, “*”);

  • 请求的url是PHP页面,则需要在PHP页面中添加代码:header(“Access-Control-Allow-Origin: *”);

  • 请求的url是静态的html页面,则需要在页面中添加meta标签代码。