UNPKG

premote

Version:

wrap javascript remote actions in a promise api

132 lines (104 loc) 3.55 kB
/*global Q:false, Visualforce:false, define:false */ (function(name, definition, root){ if(typeof exports === 'object' && typeof module === 'object') { module.exports = definition(require('q')); } else if(typeof define === 'function' && typeof define.amd === 'object') { define(['q'], definition); } else { root[name] = definition(window.Q); } })('Premote', function(Q){ 'use strict'; var Premote = {}; var Visualforce; if(!window || !window.Visualforce) { throw new Error('Visualforce Remoting manager not found'); } else { Visualforce = window.Visualforce; } // Wrap a javascript remoting function in a promise // Only works if function is properly `bind`ed to the remoting manager. This // method is private to ensure that we pass in properly bound methods. function wrapFunction (func, options) { return function() { var args; var deferred = Q.defer(); if(arguments.length) { args = Array.prototype.slice.apply(arguments); } else { args = []; } var cb = function(result, event) { if(event.status) { deferred.resolve(result); } else { var err = new Error(event.message); err.result = result; if(event.type === 'exception') { err.apexStackTrace = event.where; } deferred.reject(err); } }; args.push(cb); if(options) { args.push(options); } func.apply(null, args); return deferred.promise; }; } // public interface. Can either wrap a string remoting name ('namespace.className.remoteMethod') // or a javascript remoting class (`className`) // if provided, `options` will be appended to the promises's run-time arguments Premote.wrap = function(remoteAction, options) { if(options && typeof options !== 'object') { throw new Error('options must be an object'); } // if remoteAction is an object, wrap each of its members if (typeof remoteAction === 'object') { var ret = {}; for (var prop in remoteAction) { if (remoteAction.hasOwnProperty(prop) && typeof remoteAction[prop] === 'function') { var func = remoteAction[prop]; var boundFunc = func.bind(remoteAction); ret[prop] = wrapFunction(boundFunc, options); } } return ret; // if remoteAction is a string, turn it into a function } else if (typeof remoteAction === 'string') { // validate the string format var namespace, controller, method; var parts = remoteAction.split('.'); if(parts.length === 3) { namespace = parts[0]; controller = parts[1]; method = parts[2]; } else if(parts.length === 2) { controller = parts[0]; method = parts[1]; } else { throw new Error('invalid remote action supplied: ' + remoteAction); } var Manager = Visualforce.remoting.Manager; var bound = function () { var args; if(arguments.length) { args = Array.prototype.slice.apply(arguments); } else { args = []; } args.splice(0, 0, remoteAction); Manager.invokeAction.apply(Manager, args); }; return wrapFunction(bound, options); // remoteAction was neither an object nor a string } else { throw new Error('invalid remote action supplied: ' + remoteAction); } }; // create the global return Premote; }, (this || {}));