From 5e805ead00bbc28953bcdb08119234a348fab107 Mon Sep 17 00:00:00 2001 From: "Christian G. Warden" Date: Fri, 12 Apr 2013 15:33:07 -0700 Subject: [PATCH 1/2] Return promises from RemoteTK for compatibility with ForceTK Return a promise from each RemoteTK function for compatibility with ForceTK. Passing a callback is now optional as callbacks can be attached to the promise returned instead. Uses jQuery's Deferred promise implementation so jQuery must be loaded and available as $. --- RemoteTK.component | 73 +++++++++++++++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 23 deletions(-) diff --git a/RemoteTK.component b/RemoteTK.component index 071114a..eb8daee 100644 --- a/RemoteTK.component +++ b/RemoteTK.component @@ -32,21 +32,32 @@ if (remotetk === undefined) { } if (remotetk.Client === undefined) { - function handleResult(result, callback, error, nullok) { + function handleResult(result, callback, error, nullok, deferred) { if (result) { result = JSON.parse(result); if ( Array.isArray(result) && result[0].message && result[0].errorCode ) { if ( typeof error === 'function' ) { error(result); } + deferred.reject(result); } else { - callback(result); + if ( typeof callback === 'function' ) { + callback(result); + } + deferred.resolve(result); } } else if (typeof nullok !== 'undefined' && nullok) { - callback(); + if ( typeof callback === 'function' ) { + callback(); + } + deferred.resolve(); } else { - error([{ message : "Null return from action method","errorCode":"NULL_RETURN"}]); - } + var errorResult = [{ message : "Null return from action method","errorCode":"NULL_RETURN"}]; + if ( typeof error === 'function' ) { + error(errorResult); + } + deferred.reject(errorResult); + } } /** @@ -72,11 +83,13 @@ if (remotetk.Client === undefined) { * @param [error=null] function to which jqXHR will be passed in case of error */ remotetk.Client.prototype.describe = function(objtype, callback, error) { + var deferred = $.Deferred(); Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.RemoteTKController.describe}', objtype, function(result){ - handleResult(result, callback, error); - }, { + handleResult(result, callback, error, false, deferred); + }, { escape: false }); + return deferred.promise(); } /* @@ -89,11 +102,13 @@ if (remotetk.Client === undefined) { * @param [error=null] function to which jqXHR will be passed in case of error */ remotetk.Client.prototype.create = function(objtype, fields, callback, error) { + var deferred = $.Deferred(); Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.RemoteTKController.create}', objtype, JSON.stringify(fields), function(result){ - handleResult(result, callback, error); - }, { + handleResult(result, callback, error, false, deferred); + }, { escape: false }); + return deferred.promise(); } /* @@ -106,11 +121,13 @@ if (remotetk.Client === undefined) { * @param [error=null] function to which jqXHR will be passed in case of error */ remotetk.Client.prototype.retrieve = function(objtype, id, fieldlist, callback, error) { + var deferred = $.Deferred(); Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.RemoteTKController.retrieve}', objtype, id, fieldlist, function(result){ - handleResult(result, callback, error); - }, { + handleResult(result, callback, error, false, deferred); + }, { escape: false }); + return deferred.promise(); } /* @@ -126,11 +143,13 @@ if (remotetk.Client === undefined) { * @param [error=null] function to which jqXHR will be passed in case of error */ remotetk.Client.prototype.upsert = function(objtype, externalIdField, externalId, fields, callback, error) { + var deferred = $.Deferred(); Visualforce.remoting.Manager.invokeAction('$RemoteAction.RemoteTKController.upser', objtype, externalIdField, externalId, JSON.stringify(fields), function(result){ - handleResult(result, callback, error, true); - }, { - escape: false + handleResult(result, callback, error, true, deferred); + }, { + escape: false }); + return deferred.promise(); } /* @@ -144,11 +163,13 @@ if (remotetk.Client === undefined) { * @param [error=null] function to which jqXHR will be passed in case of error */ remotetk.Client.prototype.update = function(objtype, id, fields, callback, error) { + var deferred = $.Deferred(); Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.RemoteTKController.updat}', objtype, id, JSON.stringify(fields), function(result){ - handleResult(result, callback, error, true); - }, { + handleResult(result, callback, error, true, deferred); + }, { escape: false }); + return deferred.promise(); } /* @@ -160,11 +181,13 @@ if (remotetk.Client === undefined) { * @param [error=null] function to which jqXHR will be passed in case of error */ remotetk.Client.prototype.del = function(objtype, id, callback, error) { + var deferred = $.Deferred(); Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.RemoteTKController.del}', objtype, id, function(result){ - handleResult(result, callback, error, true); - }, { + handleResult(result, callback, error, true, deferred); + }, { escape: false }); + return deferred.promise(); } /* @@ -175,12 +198,14 @@ if (remotetk.Client === undefined) { * @param [error=null] function to which jqXHR will be passed in case of error */ remotetk.Client.prototype.query = function(soql, callback, error) { + var deferred = $.Deferred(); Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.RemoteTKController.query}', soql, function(result){ - handleResult(result, callback, error); - }, { + handleResult(result, callback, error, false, deferred); + }, { escape: false }); - } + return deferred.promise(); + } /* * Executes the specified SOSL search. @@ -190,11 +215,13 @@ if (remotetk.Client === undefined) { * @param [error=null] function to which jqXHR will be passed in case of error */ remotetk.Client.prototype.search = function(sosl, callback, error) { + var deferred = $.Deferred(); Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.RemoteTKController.search}', sosl, function(result){ - handleResult(result, callback, error); - }, { + handleResult(result, callback, error, false, deferred); + }, { escape: false }); + return deferred.promise(); } } From 2f1f38f0f2a73c0685d0dae7e52a06fab0bf044a Mon Sep 17 00:00:00 2001 From: "Christian G. Warden" Date: Tue, 7 May 2013 15:14:29 -0700 Subject: [PATCH 2/2] Handle Apex exceptions passed back to javascript remoting If an uncaught exception occurs in RemoteTKController, pass the error returned by the javascript remoting call to the error callback. --- RemoteTK.component | 88 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 72 insertions(+), 16 deletions(-) diff --git a/RemoteTK.component b/RemoteTK.component index eb8daee..6033b69 100644 --- a/RemoteTK.component +++ b/RemoteTK.component @@ -84,8 +84,15 @@ if (remotetk.Client === undefined) { */ remotetk.Client.prototype.describe = function(objtype, callback, error) { var deferred = $.Deferred(); - Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.RemoteTKController.describe}', objtype, function(result){ - handleResult(result, callback, error, false, deferred); + Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.RemoteTKController.describe}', objtype, function(result, err) { + if (err.status) { + handleResult(result, callback, error, false, deferred); + } else { + if (typeof error === 'function') { + error(err); + } + deferred.reject(err); + } }, { escape: false }); @@ -103,8 +110,15 @@ if (remotetk.Client === undefined) { */ remotetk.Client.prototype.create = function(objtype, fields, callback, error) { var deferred = $.Deferred(); - Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.RemoteTKController.create}', objtype, JSON.stringify(fields), function(result){ - handleResult(result, callback, error, false, deferred); + Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.RemoteTKController.create}', objtype, JSON.stringify(fields), function(result, err) { + if (err.status) { + handleResult(result, callback, error, false, deferred); + } else { + if (typeof error === 'function') { + error(err); + } + deferred.reject(err); + } }, { escape: false }); @@ -122,8 +136,15 @@ if (remotetk.Client === undefined) { */ remotetk.Client.prototype.retrieve = function(objtype, id, fieldlist, callback, error) { var deferred = $.Deferred(); - Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.RemoteTKController.retrieve}', objtype, id, fieldlist, function(result){ - handleResult(result, callback, error, false, deferred); + Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.RemoteTKController.retrieve}', objtype, id, fieldlist, function(result, err) { + if (err.status) { + handleResult(result, callback, error, false, deferred); + } else { + if (typeof error === 'function') { + error(err); + } + deferred.reject(err); + } }, { escape: false }); @@ -144,8 +165,15 @@ if (remotetk.Client === undefined) { */ remotetk.Client.prototype.upsert = function(objtype, externalIdField, externalId, fields, callback, error) { var deferred = $.Deferred(); - Visualforce.remoting.Manager.invokeAction('$RemoteAction.RemoteTKController.upser', objtype, externalIdField, externalId, JSON.stringify(fields), function(result){ - handleResult(result, callback, error, true, deferred); + Visualforce.remoting.Manager.invokeAction('$RemoteAction.RemoteTKController.upser', objtype, externalIdField, externalId, JSON.stringify(fields), function(result, err) { + if (err.status) { + handleResult(result, callback, error, true, deferred); + } else { + if (typeof error === 'function') { + error(err); + } + deferred.reject(err); + } }, { escape: false }); @@ -164,8 +192,15 @@ if (remotetk.Client === undefined) { */ remotetk.Client.prototype.update = function(objtype, id, fields, callback, error) { var deferred = $.Deferred(); - Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.RemoteTKController.updat}', objtype, id, JSON.stringify(fields), function(result){ - handleResult(result, callback, error, true, deferred); + Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.RemoteTKController.updat}', objtype, id, JSON.stringify(fields), function(result, err) { + if (err.status) { + handleResult(result, callback, error, true, deferred); + } else { + if (typeof error === 'function') { + error(err); + } + deferred.reject(err); + } }, { escape: false }); @@ -182,8 +217,15 @@ if (remotetk.Client === undefined) { */ remotetk.Client.prototype.del = function(objtype, id, callback, error) { var deferred = $.Deferred(); - Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.RemoteTKController.del}', objtype, id, function(result){ - handleResult(result, callback, error, true, deferred); + Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.RemoteTKController.del}', objtype, id, function(result, err) { + if (err.status) { + handleResult(result, callback, error, true, deferred); + } else { + if (typeof error === 'function') { + error(err); + } + deferred.reject(err); + } }, { escape: false }); @@ -199,8 +241,15 @@ if (remotetk.Client === undefined) { */ remotetk.Client.prototype.query = function(soql, callback, error) { var deferred = $.Deferred(); - Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.RemoteTKController.query}', soql, function(result){ - handleResult(result, callback, error, false, deferred); + Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.RemoteTKController.query}', soql, function(result, err) { + if (err.status) { + handleResult(result, callback, error, false, deferred); + } else { + if (typeof error === 'function') { + error(err); + } + deferred.reject(err); + } }, { escape: false }); @@ -216,8 +265,15 @@ if (remotetk.Client === undefined) { */ remotetk.Client.prototype.search = function(sosl, callback, error) { var deferred = $.Deferred(); - Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.RemoteTKController.search}', sosl, function(result){ - handleResult(result, callback, error, false, deferred); + Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.RemoteTKController.search}', sosl, function(result, err) { + if (err.status) { + handleResult(result, callback, error, false, deferred); + } else { + if (typeof error === 'function') { + error(err); + } + deferred.reject(err); + } }, { escape: false });