From a089699c8915636ba4f158d77dba9b012bc93208 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Fri, 4 Mar 2011 19:02:28 +0300 Subject: build custom layer of Dojo to speed up loading of tt-rss (refs #293) --- lib/dojo/rpc/JsonService.js | 107 ++++++++++++++----- lib/dojo/rpc/JsonpService.js | 80 ++++++++++---- lib/dojo/rpc/RpcService.js | 248 +++++++++++++++++++++++++++++-------------- 3 files changed, 309 insertions(+), 126 deletions(-) (limited to 'lib/dojo/rpc') diff --git a/lib/dojo/rpc/JsonService.js b/lib/dojo/rpc/JsonService.js index b88e5f531..757e328be 100644 --- a/lib/dojo/rpc/JsonService.js +++ b/lib/dojo/rpc/JsonService.js @@ -5,33 +5,86 @@ */ -if(!dojo._hasResource["dojo.rpc.JsonService"]){ -dojo._hasResource["dojo.rpc.JsonService"]=true; +if(!dojo._hasResource["dojo.rpc.JsonService"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojo.rpc.JsonService"] = true; dojo.provide("dojo.rpc.JsonService"); dojo.require("dojo.rpc.RpcService"); -dojo.declare("dojo.rpc.JsonService",dojo.rpc.RpcService,{bustCache:false,contentType:"application/json-rpc",lastSubmissionId:0,callRemote:function(_1,_2){ -var _3=new dojo.Deferred(); -this.bind(_1,_2,_3); -return _3; -},bind:function(_4,_5,_6,_7){ -var _8=dojo.rawXhrPost({url:_7||this.serviceUrl,postData:this.createRequest(_4,_5),contentType:this.contentType,timeout:this.timeout,handleAs:"json-comment-optional"}); -_8.addCallbacks(this.resultCallback(_6),this.errorCallback(_6)); -},createRequest:function(_9,_a){ -var _b={"params":_a,"method":_9,"id":++this.lastSubmissionId}; -var _c=dojo.toJson(_b); -return _c; -},parseResults:function(_d){ -if(dojo.isObject(_d)){ -if("result" in _d){ -return _d.result; -} -if("Result" in _d){ -return _d.Result; -} -if("ResultSet" in _d){ -return _d.ResultSet; -} -} -return _d; -}}); + +dojo.declare("dojo.rpc.JsonService", dojo.rpc.RpcService, { + bustCache: false, + contentType: "application/json-rpc", + lastSubmissionId: 0, + + callRemote: function(method, params){ + // summary: + // call an arbitrary remote method without requiring it to be + // predefined with SMD + // method: string + // the name of the remote method you want to call. + // params: array + // array of parameters to pass to method + + var deferred = new dojo.Deferred(); + this.bind(method, params, deferred); + return deferred; + }, + + bind: function(method, parameters, deferredRequestHandler, url){ + //summary: + // JSON-RPC bind method. Takes remote method, parameters, + // deferred, and a url, calls createRequest to make a JSON-RPC + // envelope and passes that off with bind. + // method: string + // The name of the method we are calling + // parameters: array + // The parameters we are passing off to the method + // deferredRequestHandler: deferred + // The Deferred object for this particular request + + var def = dojo.rawXhrPost({ + url: url||this.serviceUrl, + postData: this.createRequest(method, parameters), + contentType: this.contentType, + timeout: this.timeout, + handleAs: "json-comment-optional" + }); + def.addCallbacks(this.resultCallback(deferredRequestHandler), this.errorCallback(deferredRequestHandler)); + }, + + createRequest: function(method, params){ + // summary: + // create a JSON-RPC envelope for the request + // method: string + // The name of the method we are creating the requst for + // params: array + // The array of parameters for this request; + + var req = { "params": params, "method": method, "id": ++this.lastSubmissionId }; + var data = dojo.toJson(req); + return data; + }, + + parseResults: function(/*anything*/obj){ + //summary: + // parse the result envelope and pass the results back to + // the callback function + // obj: Object + // Object containing envelope of data we recieve from the server + + if(dojo.isObject(obj)){ + if("result" in obj){ + return obj.result; + } + if("Result" in obj){ + return obj.Result; + } + if("ResultSet" in obj){ + return obj.ResultSet; + } + } + return obj; + } + } +); + } diff --git a/lib/dojo/rpc/JsonpService.js b/lib/dojo/rpc/JsonpService.js index 68c971207..31e95077b 100644 --- a/lib/dojo/rpc/JsonpService.js +++ b/lib/dojo/rpc/JsonpService.js @@ -5,28 +5,68 @@ */ -if(!dojo._hasResource["dojo.rpc.JsonpService"]){ -dojo._hasResource["dojo.rpc.JsonpService"]=true; +if(!dojo._hasResource["dojo.rpc.JsonpService"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojo.rpc.JsonpService"] = true; dojo.provide("dojo.rpc.JsonpService"); dojo.require("dojo.rpc.RpcService"); dojo.require("dojo.io.script"); -dojo.declare("dojo.rpc.JsonpService",dojo.rpc.RpcService,{constructor:function(_1,_2){ -if(this.required){ -if(_2){ -dojo.mixin(this.required,_2); -} -dojo.forEach(this.required,function(_3){ -if(_3==""||_3==undefined){ -throw new Error("Required Service Argument not found: "+_3); -} + +dojo.declare("dojo.rpc.JsonpService", dojo.rpc.RpcService, { + // summary: + // Generic JSONP service. Minimally extends RpcService to allow + // easy definition of nearly any JSONP style service. Example + // SMD files exist in dojox.data + + constructor: function(args, requiredArgs){ + if(this.required) { + if(requiredArgs){ + dojo.mixin(this.required, requiredArgs); + } + + dojo.forEach(this.required, function(req){ + if(req=="" || req==undefined){ + throw new Error("Required Service Argument not found: "+req); + } + }); + } + }, + + strictArgChecks: false, + + bind: function(method, parameters, deferredRequestHandler, url){ + //summary: + // JSONP bind method. Takes remote method, parameters, + // deferred, and a url, calls createRequest to make a JSON-RPC + // envelope and passes that off with bind. + // method: string + // The name of the method we are calling + // parameters: array + // The parameters we are passing off to the method + // deferredRequestHandler: deferred + // The Deferred object for this particular request + + var def = dojo.io.script.get({ + url: url||this.serviceUrl, + callbackParamName: this.callbackParamName||"callback", + content: this.createRequest(parameters), + timeout: this.timeout, + handleAs: "json", + preventCache: true + }); + def.addCallbacks(this.resultCallback(deferredRequestHandler), this.errorCallback(deferredRequestHandler)); + }, + + createRequest: function(parameters){ + // summary: + // create a JSONP req + // params: array + // The array of parameters for this request; + + var params = (dojo.isArrayLike(parameters) && parameters.length==1) ? + parameters[0] : {}; + dojo.mixin(params,this.required); + return params; + } }); -} -},strictArgChecks:false,bind:function(_4,_5,_6,_7){ -var _8=dojo.io.script.get({url:_7||this.serviceUrl,callbackParamName:this.callbackParamName||"callback",content:this.createRequest(_5),timeout:this.timeout,handleAs:"json",preventCache:true}); -_8.addCallbacks(this.resultCallback(_6),this.errorCallback(_6)); -},createRequest:function(_9){ -var _a=(dojo.isArrayLike(_9)&&_9.length==1)?_9[0]:{}; -dojo.mixin(_a,this.required); -return _a; -}}); + } diff --git a/lib/dojo/rpc/RpcService.js b/lib/dojo/rpc/RpcService.js index 03c6a46b6..7ff71415e 100644 --- a/lib/dojo/rpc/RpcService.js +++ b/lib/dojo/rpc/RpcService.js @@ -5,85 +5,175 @@ */ -if(!dojo._hasResource["dojo.rpc.RpcService"]){ -dojo._hasResource["dojo.rpc.RpcService"]=true; +if(!dojo._hasResource["dojo.rpc.RpcService"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojo.rpc.RpcService"] = true; dojo.provide("dojo.rpc.RpcService"); -dojo.declare("dojo.rpc.RpcService",null,{constructor:function(_1){ -if(_1){ -if((dojo.isString(_1))||(_1 instanceof dojo._Url)){ -if(_1 instanceof dojo._Url){ -var _2=_1+""; -}else{ -_2=_1; -} -var _3=dojo.xhrGet({url:_2,handleAs:"json-comment-optional",sync:true}); -_3.addCallback(this,"processSmd"); -_3.addErrback(function(){ -throw new Error("Unable to load SMD from "+_1); -}); -}else{ -if(_1.smdStr){ -this.processSmd(dojo.eval("("+_1.smdStr+")")); -}else{ -if(_1.serviceUrl){ -this.serviceUrl=_1.serviceUrl; -} -this.timeout=_1.timeout||3000; -if("strictArgChecks" in _1){ -this.strictArgChecks=_1.strictArgChecks; -} -this.processSmd(_1); -} -} -} -},strictArgChecks:true,serviceUrl:"",parseResults:function(_4){ -return _4; -},errorCallback:function(_5){ -return function(_6){ -_5.errback(_6.message); -}; -},resultCallback:function(_7){ -var tf=dojo.hitch(this,function(_8){ -if(_8.error!=null){ -var _9; -if(typeof _8.error=="object"){ -_9=new Error(_8.error.message); -_9.code=_8.error.code; -_9.error=_8.error.error; -}else{ -_9=new Error(_8.error); -} -_9.id=_8.id; -_9.errorObject=_8; -_7.errback(_9); -}else{ -_7.callback(this.parseResults(_8)); -} -}); -return tf; -},generateMethod:function(_a,_b,_c){ -return dojo.hitch(this,function(){ -var _d=new dojo.Deferred(); -if((this.strictArgChecks)&&(_b!=null)&&(arguments.length!=_b.length)){ -throw new Error("Invalid number of parameters for remote method."); -}else{ -this.bind(_a,dojo._toArray(arguments),_d,_c); -} -return _d; + +dojo.declare("dojo.rpc.RpcService", null, { + constructor: function(args){ + //summary: + //Take a string as a url to retrieve an smd or an object that is an smd or partial smd to use + //as a definition for the service + // + // args: object + // Takes a number of properties as kwArgs for defining the service. It also + // accepts a string. When passed a string, it is treated as a url from + // which it should synchronously retrieve an smd file. Otherwise it is a kwArgs + // object. It accepts serviceUrl, to manually define a url for the rpc service + // allowing the rpc system to be used without an smd definition. strictArgChecks + // forces the system to verify that the # of arguments provided in a call + // matches those defined in the smd. smdString allows a developer to pass + // a jsonString directly, which will be converted into an object or alternatively + // smdObject is accepts an smdObject directly. + // + if(args){ + //if the arg is a string, we assume it is a url to retrieve an smd definition from + if( (dojo.isString(args)) || (args instanceof dojo._Url)){ + if (args instanceof dojo._Url){ + var url = args + ""; + }else{ + url = args; + } + var def = dojo.xhrGet({ + url: url, + handleAs: "json-comment-optional", + sync: true + }); + + def.addCallback(this, "processSmd"); + def.addErrback(function() { + throw new Error("Unable to load SMD from " + args); + }); + + }else if(args.smdStr){ + this.processSmd(dojo.eval("("+args.smdStr+")")); + }else{ + // otherwise we assume it's an arguments object with the following + // (optional) properties: + // - serviceUrl + // - strictArgChecks + // - smdStr + // - smdObj + + if(args.serviceUrl){ + this.serviceUrl = args.serviceUrl; + } + + this.timeout = args.timeout || 3000; + + if("strictArgChecks" in args){ + this.strictArgChecks = args.strictArgChecks; + } + + this.processSmd(args); + } + } + }, + + strictArgChecks: true, + serviceUrl: "", + + parseResults: function(obj){ + // summary + // parse the results coming back from an rpc request. this + // base implementation, just returns the full object + // subclasses should parse and only return the actual results + // obj: Object + // Object that is the return results from an rpc request + return obj; + }, + + errorCallback: function(/* dojo.Deferred */ deferredRequestHandler){ + // summary: + // create callback that calls the Deferres errback method + // deferredRequestHandler: Deferred + // The deferred object handling a request. + return function(data){ + deferredRequestHandler.errback(data.message); + }; + }, + + resultCallback: function(/* dojo.Deferred */ deferredRequestHandler){ + // summary: + // create callback that calls the Deferred's callback method + // deferredRequestHandler: Deferred + // The deferred object handling a request. + + var tf = dojo.hitch(this, + function(obj){ + if(obj.error!=null){ + var err; + if(typeof obj.error == 'object'){ + err = new Error(obj.error.message); + err.code = obj.error.code; + err.error = obj.error.error; + }else{ + err = new Error(obj.error); + } + err.id = obj.id; + err.errorObject = obj; + deferredRequestHandler.errback(err); + }else{ + deferredRequestHandler.callback(this.parseResults(obj)); + } + } + ); + return tf; + }, + + generateMethod: function(/*string*/ method, /*array*/ parameters, /*string*/ url){ + // summary: + // generate the local bind methods for the remote object + // method: string + // The name of the method we are generating + // parameters: array + // the array of parameters for this call. + // url: string + // the service url for this call + + return dojo.hitch(this, function(){ + var deferredRequestHandler = new dojo.Deferred(); + + // if params weren't specified, then we can assume it's varargs + if( (this.strictArgChecks) && + (parameters != null) && + (arguments.length != parameters.length) + ){ + // put error stuff here, no enough params + throw new Error("Invalid number of parameters for remote method."); + }else{ + this.bind(method, dojo._toArray(arguments), deferredRequestHandler, url); + } + + return deferredRequestHandler; + }); + }, + + processSmd: function(object){ + // summary: + // callback method for reciept of a smd object. Parse the smd + // and generate functions based on the description + // object: + // smd object defining this service. + + if(object.methods){ + dojo.forEach(object.methods, function(m){ + if(m && m.name){ + this[m.name] = this.generateMethod( m.name, + m.parameters, + m.url||m.serviceUrl||m.serviceURL); + if(!dojo.isFunction(this[m.name])){ + throw new Error("RpcService: Failed to create" + m.name + "()"); + /*console.log("RpcService: Failed to create", m.name, "()");*/ + } + } + }, this); + } + + this.serviceUrl = object.serviceUrl||object.serviceURL; + this.required = object.required; + this.smd = object; + } }); -},processSmd:function(_e){ -if(_e.methods){ -dojo.forEach(_e.methods,function(m){ -if(m&&m.name){ -this[m.name]=this.generateMethod(m.name,m.parameters,m.url||m.serviceUrl||m.serviceURL); -if(!dojo.isFunction(this[m.name])){ -throw new Error("RpcService: Failed to create"+m.name+"()"); -} -} -},this); -} -this.serviceUrl=_e.serviceUrl||_e.serviceURL; -this.required=_e.required; -this.smd=_e; -}}); + } -- cgit v1.2.3