implement basic DOM Future and FutureResolver mechanism
authorLuc Yriarte <luc.yriarte@intel.com>
Wed, 22 May 2013 15:01:56 +0000 (17:01 +0200)
committerLuc Yriarte <luc.yriarte@intel.com>
Wed, 22 May 2013 15:01:56 +0000 (17:01 +0200)
cloudeebus/cloudeebus.js

index ef33be1..847b552 100644 (file)
@@ -151,20 +151,145 @@ cloudeebus.BusConnection.prototype.getObject = function(busName, objectPath, int
 
 /*****************************************************************************/
 
-cloudeebus.Request = function(proxy, onsuccess, onerror) {
-       this.proxy = proxy; 
-       this.readyState = "pending";
-       this.error = null;
+function _processWrappers(wrappers, value) {
+       for (var i=0; i<wrappers.length; i++)
+               wrappers[i](value);
+}
+
+
+function _processWrappersAsync(wrappers, value) {
+       var taskid = -1;
+       function processAsyncOnce() {
+               _processWrappers(wrappers, value);
+               clearInterval(taskid);
+       }
+       taskid = setInterval(processAsyncOnce, 200);
+}
+
+
+
+/*****************************************************************************/
+
+cloudeebus.FutureResolver = function(future) {
+       this.future = future;
+       this.resolved = null;
+    return this;
+};
+
+
+cloudeebus.FutureResolver.prototype.resolve = function(value, sync) {
+       if (this.resolved)
+               return;
+       
+       try {
+               this.accept(value, sync);
+       }
+       catch (e) {
+               this.reject(e, sync);
+       }
+};
+
+
+cloudeebus.FutureResolver.prototype.accept = function(value, sync) {
+       if (this.resolved)
+               return;
+       
+       var future = this.future;
+       future.state = "accepted";
+       future.result = value;
+       
+       this.resolved = true;
+       if (sync)
+               _processWrappers(future._acceptWrappers, value);
+       else
+               _processWrappersAsync(future._acceptWrappers, value);
+};
+
+
+cloudeebus.FutureResolver.prototype.reject = function(value, sync) {
+       if (this.resolved)
+               return;
+       
+       var future = this.future;
+       future.state = "rejected";
+       future.result = value;
+       
+       this.resolved = true;
+       if (sync)
+               _processWrappers(future._rejectWrappers, value);
+       else
+               _processWrappersAsync(future._rejectWrappers, value);
+};
+
+
+
+/*****************************************************************************/
+
+cloudeebus.Future = function(init) {
+       this.state = "pending";
        this.result = null;
-       this.onsuccess = onsuccess;
-       this.onerror = onerror;
+       this._acceptWrappers = [];
+       this._rejectWrappers = [];
+       this.resolver = new cloudeebus.FutureResolver(this);
+       if (init) {
+               try {
+                       init.apply(this, [this.resolver]);
+               }
+               catch (e) {
+                       this.resolver.reject(e, true);
+               }
+       }
     return this;
 };
 
-cloudeebus.Request.prototype.then = function(onsuccess, onerror) {
-       this.onsuccess = onsuccess;
-       this.onerror = onerror;
-       return this;
+
+cloudeebus.Future.prototype.appendWrappers = function(acceptWrapper, rejectWrapper) {
+       this._acceptWrappers.push(acceptWrapper);
+       this._rejectWrappers.push(rejectWrapper);
+       if (this.state == "accepted")
+               _processWrappersAsync(this._acceptWrappers, this.result);
+       if (this.state == "rejected")
+               _processWrappersAsync(this._rejectWrappers, this.result);
+};
+
+
+cloudeebus.Future.prototype.then = function(acceptCB, rejectCB) {
+       var future = new cloudeebus.Future();
+       var resolver = future.resolver;
+       var acceptWrapper, rejectWrapper;
+       
+       if (acceptCB)
+               acceptWrapper = function(arg) {
+                       try {
+                               var value = acceptCB.apply(future, [arg]);
+                               resolver.accept(value, true);
+                       }
+                       catch (e) {
+                               resolver.reject(e, true);
+                       }
+               };
+       else
+               acceptWrapper = function(arg) {
+                       resolver.accept(arg, true);
+               };
+       
+       if (rejectCB)
+               rejectWrapper = function(arg) {
+                       try {
+                               var value = rejectCB.apply(future, [arg]);
+                               resolver.reject(value, true);
+                       }
+                       catch (e) {
+                               resolver.reject(e, true);
+                       }
+               };
+       else
+               rejectWrapper = function(arg) {
+                       resolver.reject(arg, true);
+               };
+       
+       this.appendWrappers(acceptWrapper,rejectWrapper);
+       return future;
 };
 
 
@@ -280,47 +405,42 @@ cloudeebus.ProxyObject.prototype._addMethod = function(ifName, method, nArgs, si
        };      
 };
 
+
 cloudeebus.ProxyObject.prototype.callMethod = function(ifName, method, args, signature) {
        
        var self = this;
-       var request = new cloudeebus.Request(this);
        
-       function callMethodSuccessCB(str) {
-               request.readyState = "done";
-               try { // calling dbus hook object function for un-translated types
-                       var result = eval(str);
-                       request.result = result[0];
-                       if (request.onsuccess)
-                               request.onsuccess.apply(request, result);
-               }
-               catch (e) {
-                       cloudeebus.log("Method callback exception: " + e);
-                       request.error = e;
-                       if (request.onerror)
-                               request.onerror.apply(request, [request.error]);
+       var future = new cloudeebus.Future(function (resolver) {
+               function callMethodSuccessCB(str) {
+                       try { // calling dbus hook object function for un-translated types
+                               var result = eval(str);
+                               resolver.accept(result[0]);
+                       }
+                       catch (e) {
+                               cloudeebus.log("Method callback exception: " + e);
+                               resolver.reject(e);
+                       }
                }
-       }
-
-       function callMethodErrorCB(error) {
-               cloudeebus.log("Error calling method: " + method + " on object: " + self.objectPath + " : " + error.desc);
-               request.readyState = "done";
-               request.error = error.desc;
-               if (request.onerror)
-                       request.onerror.apply(request, [request.error]);
-       }
 
-       var arglist = [
-               self.busConnection.name,
-               self.busName,
-               self.objectPath,
-               ifName,
-               method,
-               JSON.stringify(args)
-       ];
+               function callMethodErrorCB(error) {
+                       cloudeebus.log("Error calling method: " + method + " on object: " + self.objectPath + " : " + error.desc);
+                       resolver.reject(error.desc);
+               }
 
-       // call dbusSend with bus type, destination, object, message and arguments
-       self.wampSession.call("dbusSend", arglist).then(callMethodSuccessCB, callMethodErrorCB);
-       return request;
+               var arglist = [
+                       self.busConnection.name,
+                       self.busName,
+                       self.objectPath,
+                       ifName,
+                       method,
+                       JSON.stringify(args)
+               ];
+
+               // call dbusSend with bus type, destination, object, message and arguments
+               self.wampSession.call("dbusSend", arglist).then(callMethodSuccessCB, callMethodErrorCB);
+       });
+       
+       return future;
 };