在用到FLEX的AMF信道进行远程通讯过程中,很多人都碰到一个问题:实例化一个RemoteObject对象,调用多个服务端函数和指定resultHandler()来作不同的处理。
而且我们希望远程函数调用与本地的函数调用区别开来,新手进来也不容易困惑~!
下面我们来讲讲以上的问题怎么解决!
//1、派生一个RemoteObject来实现我们想要的功能
public class HtRemoteObject extends mx.rpc.remoting.mxml.RemoteObject
//指定默认的失败回调函数,成功的回调在创建远程调用时指定,不需要默认的,这样在我们使用时只要指定成功的回调就行了,失败的就用默认的,这样省去每次都要指定两个回调的麻烦。
public var onResult:Function=null;
public var onFault:Function = HtRemoteObject.onFaultDefault;
// 用户自定义对象,在返回的事件中 e.token.ids 中可获取到,要扩展远程调用就是简单的事情了,哈哈。
public var ids:Object=null;
/**
* 构造函数
* @param destination 网关的终点
* @param source 远端函数的命名空间和类名,也就是远端函数所处的位置
* @param debug 是否连接调试服务器(调试模式)
* @param showBusyCursor 是否显示鼠标忙指针
*
*/
public function HtRemoteObject(destination:String=null, source:String=null, debug:Boolean=false, showBusyCursor:Boolean=false)
{
if(destination==null)
destination=HtRemoteObject.DESTINATION;
if(source==null)
source=HtRemoteObject.SysInfoInterface;
super(destination);
super.source=source;
super.showBusyCursor=showBusyCursor; //鼠标指针忙
if (debug || fdgModel.config.isDebug)
{
//fdgModel为我的数据模型,大家可以自行构造自己的数据模型。
super.endpoint=fdgModel.config.serverUrl + "/Gateway.aspx";//指定服务器端点调试时使用
}
}
/**
* 远程通讯,默认的失败处理函数
* @param e 事件
*
*/
static public function onFaultDefault(e:FaultEvent):void
{
CursorManager.removeBusyCursor();
try {
throw new HtError("远程服务器错误:" + mx.utils.ObjectUtil.toString(e), e.fault.faultCode as int);
}
catch (err:Error)
{
ht.errors.HtError.showError(err);
}
}
/**
* 远程调用 Server 中的函数
* @foo 函数名
* @args 参数列表
*/
public function call(foo:String, ...args):void
{
if(foo.length==0)
throw new Error("foo can not be empty!");
//创建一个远程调用函数
var operation:AbstractOperation=this.getOperation(foo);
//Token
var call:AsyncToken = operation.send.apply(null, args);
// ids 中承载了处理函数和用户自定义ids,在 onDSResultParser onFaultParser 中解析和处理
var idsWapper : Object = new Object;
//使用自定的错误回调函数由onFaultParser调度,使用前要设定this.onFault
idsWapper.onFaultCB = this.onFault;
//使用自定的正确回调函数由onResultParser调度,使用时要设定this.onResult
idsWapper.onResultCB = this.onResult;
idsWapper.ids = this.ids;
//如果要显示进程
idsWapper.progress = progress;
call.ids = idsWapper;
//设定回调处理器
call.addResponder(new mx.rpc.Responder(HtRemoteObject.onResultParser,
HtRemoteObject.onFaultParser) as IResponder);
}
/**
* 处理服务器返回的数据,如果正确,则调用'数据返回回调',错误则调用'错误处理回调'
* @param evt 成功事件
*
*/
static protected function onResultParser(e:ResultEvent):void
{
try
{
var idsWapper : Object = e.token.ids;
// 删除进度条对象
if (null != idsWapper.progress)
{
var progress : UIComponent = idsWapper.progress as UIComponent;
idsWapper.progress = null;
if (null != progress && null != progress.parent && progress.parent.contains(progress))
progress.parent.removeChild(progress);
}
CursorManager.removeBusyCursor();
var onResult : Function = idsWapper.onResultCB as Function;
e.token.ids = idsWapper.ids;
if (null != onResult)
onResult (e);
}
catch(err:Error)
{
ht.errors.HtError.showError(err);
}
}
static protected function onFaultParser(e:FaultEvent):void
{
try
{
var idsWapper : Object = e.token.ids;
// 删除进度条对象
if (null != idsWapper.progress)
{
var progress : UIComponent = idsWapper.progress as UIComponent;
idsWapper.progress = null;
if (null != progress && null != progress.parent && progress.parent.contains(progress))
progress.parent.removeChild(progress);
}
CursorManager.removeBusyCursor();
var onFault : Function = idsWapper.onFaultCB as Function;
e.token.ids = idsWapper.ids;
if (null == onFault)
onFault = HtRemoteObject.onFaultDefault;
onFault(e);
}
catch(err:Error)
{
ht.errors.HtError.showError(err);
}
}
以下为升级版的补充说明:Flex远程调用批量打包通讯库
批量远程通讯接口类
建议所有请求都使用本类
数据缓冲池对象(FXGlobalModel)的rpc是本类的实例
使用的方法:
1、基于数据缓冲池访问WS:设置onFault; onResult; addCaller; 即可
2、远程调用:如需要全部请求返回后进行回调处理,则设置 onAllResult; onAllFault; 这时,调用 commit 后才会提交addDSCaller、addCaller的请求
3、请用WSRemoteObject 此类,不要直接用HtRemoteObject
4、返回的格式为:{ code: 0, ret: Object }, 错误时为:{ code: numErrorCode, what: strErrorMsg }
5、最佳使用方式:在某个单例对象中实例化WSRemoteObject :public var rpc:WSRemoteObject; 调用时可以 XXX.rpc....这样操作,如:
XXX.currModel.rpc.onFault = onQueryFault;
XXX.currModel.rpc.onResult = onQueryResult;
XXX.currModel.rpc.addCaller(NetHandler.DATA_ACCESS_INTERFACE, "QueryOBD", queryInfo);
//此行可以不用, 不用时请在系统的某处判断rpc.callNumber>0时再commit(),也可以设定某个时间间隔来定时做此判断,比如3s或10s也可以1s,就看大家的需要了
XXX.currModel.rpc.commit();
设置:
1、请在工程的编译参数加入-services引用此标准的RO设置(./WEB-INF/flex/services-config.xml)
2、以上文件包含此项endpoint(动态取URL值):<endpoint uri="http://{server.name}:{server.port}/{context.root}/[page.php|aspx|jsp]" class="flex.messaging.endpoints.AMFEndpoint"/>(请参考官方讲解)
3、debug开启时,可用FXConfig.SERVER_URL指定通讯地址
4、destination可通过FXConfig.CURR_DESTINATION 指定,但建议用-services的指定,如asp.net的为 fluorine ,php的为zend 或 amfphp 等等,具体看用哪种服务端
补:使用时请详细查看API参考里的 FXConfig 类与 WSRemoteObject 类,再有就是 WSRemoteObject 支持的事件:RpcEvent.RPC_ERROR 此事件会在返回值code > 0 时发出,可以这样处理:
private function rpcErrorHandler(e:RpcEvent):void
{
if (e.errorObject is Error)
//LogError(e.errorObject as Error);
else if (e.errorObject is FaultEvent)
//LogErrorEvent(e.errorObject as FaultEvent);
}
附下载地址:http://code.google.com/p/flex-rpc/
请看完这个: http://code.google.com/p/flex-rpc/wiki/FlexRPC_Help