Egret MVC通用框架HTTP请求实践(GET请求)

参考资料:
URLLoader网络通讯
Egret游戏通用开发框架–MVC篇

在原有MVC的基础上, 增加了一层Proxy用于进行通信。

  • BaseModel,是Model的基类,负责该Module的数据存储,每个Module只存在一个Model
  • BaseGuiView、BaseSpriteView,是View的基类,都实现了IBaseView接口,负责该Module的View层显示及View层的基础逻辑,两个类的不同在于,BaseGuiView继承自egret.gui.SkinnableContainer,用于使用GUI的View,BaseSpriteView继承自egret.Sprite,用于不使用GUI的View,每个Module可以有多个View
  • BaseController,是Controller的基类,负责Module内部、Module与Module之间的事件交互,每个Module只存在一个Controller
  • BaseProxy,是Proxy的基类,负责该Module与服务器的数据通信交互,支持Http和WebSocket

实例

财富榜实例文件结构

如何请求数据

在Controller构造函数中初始化模块内的View、Proxy、Model,并且注册模块内、模块内部事件监听

1
2
3
4
public constructor() {
this.registerFunc(JackWealthConst.GAMERANKING_C2S, this.getGameRanking, this)
this.registerFunc(JackWealthConst.GAMERANKING_S2C, this.getGameRankingSuccess, this)
}

在getGameRanking()方法中,调用Proxy的方法,用以HTTP请求,此时需要获取到GET请求所需的参数,这里只需要获取gameID

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
   /**
* 请求获取财富值排行榜处理
*/
private getGameRanking(): void {
let userInfo:any = egret.localStorage.getItem(JackGameConst.Get_User_Information)
let gameId:string = JSON.parse(userInfo).gameId

this.jackWealthProxy.getGameRanking(gameId)
}


//Proxy.ts
public getGameRanking(gameId: string): void {
let param: string = `/gameRanking?gameId=${gameId}`

this.getHttpMsg(HttpConst.JACK_GAME_RANKING, param)
}

在Proxy中,需要注册从服务器返回的消息监听,并有相应的处理函数,用以通知Controller数据请求成功

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class JackWealthProxy extends BaseProxy {
public constructor($controller: BaseController) {
super($controller);
//注册从服务器返回消息的监听
this.receiveServerMsg(HttpConst.JACK_GAME_RANKING, this.getGameRankingSuccess, this);
}


public getGameRanking(gameId: string): void {
let param: string = `/gameRanking?gameId=${gameId}`

this.getHttpMsg(HttpConst.JACK_GAME_RANKING, param)
}


private getGameRankingSuccess(obj: any): void {
this.applyFunc(JackWealthConst.GAMERANKING_S2C, obj)
}
}

数据请求成功

在Controller中已经注册了监听到数据请求成功的处理函数,在该处理函数中完成模块所需的逻辑处理

1
2
3
4
5
6
7
8
9
/**
* 请求获取财富值排行榜成功
*/
private getGameRankingSuccess(gameRanking: any): void {
//保存数据
this.jackWealthModel.gameRanking = gameRanking
//本模块UI的处理
this.addItemToWealth()
}

扩展框架的HTTP请求

框架原有的请求方法中,只写了POST(可能有误?)

参考URLLoader网络通讯

修改 /core/net/http/Http.ts

增加所需要的属性

当我们需要创建一个网络连接的时候,我们需要创建一个 URLLoader 对象,该对象负责网络的连接状态操作, 同时负责接收网络回传的数据。网络通信时,需要的网络通信数据由 URLRequest 对象负责管理。

1
2
3
4
5
//GET请求相关属性
private _getRequest: egret.URLRequest //URL请求对象
private _getCache: Array<any> //请求缓存,其实数组,实现按顺序请求
private _isGetRequesting: boolean //是否在请求的标志符
private _urlGetLoader: egret.URLLoader; //

初始化属性和添加事件监听

1
2
3
4
5
6
7
this._getRequest = new egret.URLRequest()
this._getRequest.method = egret.URLRequestMethod.GET

this._getCache = []

this._urlGetLoader = new egret.URLLoader()
this._urlGetLoader.addEventListener(egret.IOErrorEvent.IO_ERROR, this.onGetError, this)

核心方法

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
/**
* 增加HTTP GET请求数据方法
*/
public getData(type: string, param: string): void {
this._getCache.push([type, param])
this.get()
}

private get(): void {
if (this._isGetRequesting) {
return
}

if (this._getCache.length == 0) {
return
}

let arr: Array<any> = this._getCache.shift()
let type: string = arr[0]
let getparam: string = arr[1]
this._type = type

this._getRequest.url = this._serverUrl + getparam

this._urlGetLoader.addEventListener(egret.Event.COMPLETE, this.onGetLoaderComplete, this)
this._urlGetLoader.load(this._getRequest)
this._isGetRequesting = true
}

请求成功之后需要派发相应事件,需要注意的这个时间的类型,就是之前在Proxy方法中参数的 this.getHttpMsg(HttpConst.JACK_GAME_RANKING, param)

1
2
3
4
5
6
7
8
9
10
11
12
private onGetLoaderComplete(event: egret.Event): void {
this._urlGetLoader.removeEventListener(egret.Event.COMPLETE, this.onGetLoaderComplete, this)

let msg: any = JSON.parse(this._urlGetLoader.data)

if (msg) {
App.MessageCenter.dispatch(this._type, msg)
} else {
Log.trace("Http错误")
}
this.nextGet();
}

派发事件后,在相应注册了事件监听Controller中就能拿到请求成功的数据msg了,用以保存到Model、通知view进行相应的数据渲染

渲染结果