Skip to content

Instantly share code, notes, and snippets.

@darscan
Created July 10, 2010 16:46
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save darscan/470851 to your computer and use it in GitHub Desktop.
Save darscan/470851 to your computer and use it in GitHub Desktop.
Promises and Services (old). Please see: http://github.com/darscan/robotlegs-extensions-Oil
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 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
Author

darscan commented Oct 14, 2010

Promise is not the right name for this. Operation might be better.

@quantuminformation
Copy link

Nice mate, could you provide an implementation suitable for AMF?

@vrobel
Copy link

vrobel commented Oct 24, 2010

@quantuminformation You can check it out on my forked version: http://gist.github.com/643492

@darscan Could you check if there's everything good about proper adding event handlers for NetConnection object?

@darscan
Copy link
Author

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

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