Skip to content

Instantly share code, notes, and snippets.

@vrobel
Forked from darscan/JsonRemoteService.as
Created October 24, 2010 12:11
Show Gist options
  • Save vrobel/643492 to your computer and use it in GitHub Desktop.
Save vrobel/643492 to your computer and use it in GitHub Desktop.
package org.robotlegs.utilities.remote
{
import com.adobe.serializers.json.JSONDecoder;
import mx.collections.ArrayCollection;
public class JsonRemoteService extends RemoteServiceBase
{
public function JsonRemoteService(rootURL:String = "")
{
super(rootURL);
}
override protected function generateObject(data:*):Object
{
// Hack:
if (data == "[]")
return new ArrayCollection();
return new JSONDecoder().decode(String(data));
}
}
}
package org.robotlegs.utilities.remote {
public interface NetConnectionService {
function call(gatewayUrl:String, remoteMethod:String, ...rest):Promise
function closeConnection(gatewayUrl:String) : void
}
}
package org.robotlegs.utilities.remote {
import flash.events.NetStatusEvent;
import flash.events.SecurityErrorEvent;
import flash.net.NetConnection;
import flash.net.ObjectEncoding;
import flash.net.Responder;
import flash.utils.Dictionary;
public class NetConnectionServiceBase implements INetConnectionService {
protected var netConnections:Dictionary;
protected var promises:Array;
public function NetConnectionServiceBase() {
netConnections = new Dictionary();
promises = []
}
public function call(gatewayUrl:String, remoteMethod:String, ...rest):Promise {
var nc:NetConnection = getNetConnection(gatewayUrl);
var p:Promise = request(nc, remoteMethod, rest);
nc.addEventListener(NetStatusEvent.NET_STATUS, createHandler(handleNetStatus,p), false, 0, true);
nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR, createHandler(handleSecurityError,p), false, 0, true);
return p;
}
private function getNetConnection(gatewayUrl:String):NetConnection {
if(netConnections[gatewayUrl])
return netConnections[gatewayUrl];
else {
var nc:NetConnection = new NetConnection();
nc.objectEncoding = ObjectEncoding.AMF3;
nc.connect(gatewayUrl);
netConnections[gatewayUrl] = nc;
return nc;
}
}
public function closeConnection(gatewayUrl:String) : void {
if(netConnections[gatewayUrl]) {
(netConnections[gatewayUrl] as NetConnection).close();
delete netConnections[gatewayUrl];
}
}
protected function request(nc:NetConnection, rm:String, params:Array):Promise {
var p:Promise = new Promise;
var res:Responder = new Responder(createHandler(handleComplete, p), createHandler(handleIoError, p));
nc.call.apply(this, [rm, res].concat(params));
promises.push(p);
return p;
}
protected function releasePromise(promise:Promise):void {
var index:int = promises.indexOf(promise);
if (index != -1) {
promises.splice(index, 1);
}
}
/* ----------- HANDLERS ----------- */
private function handleNetStatus(e:Object, promise:Promise):void {
switch (e.info.code) {
case "NetConnection.Call.Failed":
releasePromise(promise);
promise.handleFault({ error: "NetConnection Error", message: 'NetConnection call failed' });
break;
case "NetConnection.Connect.Failed":
releasePromise(promise);
promise.handleFault({ error: "NetConnection Error", message: 'NetConnection connect failed' });
break;
}
}
private function handleSecurityError(e:Object, promise:Promise):void {
releasePromise(promise);
promise.handleFault({ error: "Security Error", message: String(e.text) });
}
protected function handleIoError(e:Object, promise:Promise):void {
releasePromise(promise);
promise.handleFault({ error: "IO Error", message: String(e.faultString + " ON " + e.faultDetail + " " + e.faultCode) });
}
protected function handleComplete(r:Object, promise:Promise):void {
releasePromise(promise);
promise.handleResult( generateObject( r ) );
}
/* ----------- END HANDLERS ----------- */
protected function createHandler(listener:Function, promise:Promise):Function {
return function(obj:Object):void {
listener(obj, promise);
}
}
protected function generateObject(data:*):Object {
return Object(data);
}
}
}
package org.robotlegs.utilities.remote
{
public class Promise
{
public static var PENDING:String = "pending";
public static var COMPLETE:String = "complete";
public static var FAILED:String = "failed";
public static var CANCELLED:String = "cancelled";
protected var resultHandlers:Array;
protected var faultHandlers:Array;
[Bindable]
public var status:String;
[Bindable]
public var result:*;
[Bindable]
public var fault:*;
public function Promise()
{
status = PENDING;
resetHandlers();
}
public function addResultHandler(handler:Function):Promise
{
if (status == COMPLETE)
{
handler(this);
}
else if (status == PENDING && resultHandlers.indexOf(handler) == -1)
{
resultHandlers.push(handler);
}
return this;
}
public function addFaultHandler(handler:Function):Promise
{
if (status == FAILED)
{
handler(this);
}
else if (status == PENDING && faultHandlers.indexOf(handler) == -1)
{
faultHandlers.push(handler);
}
return this;
}
public function handleResult(obj:Object):void
{
status = COMPLETE;
result = obj;
var len:int = resultHandlers.length;
for (var i:int = 0; i < len; i++)
{
var handler:Function = resultHandlers[i];
handler(this);
}
resetHandlers();
}
public function handleFault(obj:Object):void
{
status = FAILED;
fault = obj;
var len:int = faultHandlers.length;
for (var i:int = 0; i < len; i++)
{
var handler:Function = faultHandlers[i];
handler(this);
}
resetHandlers();
}
public function cancel():void
{
status = CANCELLED;
resetHandlers();
}
protected function resetHandlers():void
{
resultHandlers = [];
faultHandlers = [];
}
}
}
package org.robotlegs.utilities.remote
{
public interface RemoteService
{
function get(url:String):Promise;
function post(url:String, params:Object = null):Promise;
}
}
package org.robotlegs.utilities.remote
{
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.events.SecurityErrorEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.net.URLRequestMethod;
import flash.net.URLVariables;
import flash.utils.Dictionary;
public class RemoteServiceBase implements RemoteService
{
protected var loaders:Dictionary;
protected var promises:Array;
protected var rootURL:String;
public function RemoteServiceBase(rootURL:String = "")
{
this.loaders = new Dictionary();
this.promises = new Array();
this.rootURL = rootURL;
}
public function get(url:String):Promise
{
var req:URLRequest = new URLRequest(fullUrl(url));
return request(req);
}
public function post(url:String, params:Object = null):Promise
{
var req:URLRequest = new URLRequest(fullUrl(url));
var vars:URLVariables = new URLVariables();
// Flash Player seems to perform a GET if no params are passed
params ||= {forcePost:true};
for (var prop:String in params)
vars[prop] = params[prop];
req.data = vars;
req.method = URLRequestMethod.POST;
return request(req);
}
protected function request(req:URLRequest):Promise
{
var promise:Promise = new Promise();
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, createHandler(handleComplete, promise));
loader.addEventListener(IOErrorEvent.IO_ERROR, createHandler(handleIoError, promise));
loader.addEventListener(ProgressEvent.PROGRESS, createHandler(handleProgress, promise));
loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, createHandler(handleSecurity, promise));
promises.push(promise);
loaders[promise] = loader;
loader.load(req);
return promise;
}
protected function releasePromise(promise:Promise):void
{
var index:int = promises.indexOf(promise);
if (index != -1)
{
promises.splice(index, 1);
delete loaders[promise];
}
}
protected function createHandler(listener:Function, promise:Promise):Function
{
return function(event:Event):void
{
listener(event, promise);
}
}
protected function handleSecurity(e:SecurityErrorEvent, promise:Promise):void
{
releasePromise(promise);
promise.handleFault({error: "Security Error", message: e.text});
}
protected function handleProgress(e:ProgressEvent, promise:Promise):void
{
// promise.handleProgress({bytesTotal: e.bytesTotal, bytesLoaded: e.bytesLoaded});
}
protected function handleIoError(e:IOErrorEvent, promise:Promise):void
{
releasePromise(promise);
promise.handleFault({error: "IO Error", message: e.text});
}
protected function handleComplete(e:Event, promise:Promise):void
{
releasePromise(promise);
promise.handleResult(generateObject(e.target.data));
}
protected function fullUrl(url:String):String
{
if (url == null || url.length == 0)
return null;
return url.indexOf("://") > -1 ? url : rootURL + url;
}
protected function generateObject(data:*):Object
{
return Object(data);
}
}
}
@darscan
Copy link

darscan commented Oct 28, 2010

@wrobel221 I've moved this stuff into a new RL extension called Oil: http://github.com/darscan/robotlegs-extensions-Oil

Feel free to fork from there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment