Here’s another quick braindump post. A custom JSON-RPC library I wrote for a project at my last job. It should follow the JSON-RPC 2.0 Spec pretty closely. It does require the jQuery library as well.
You can pretty much ignore the MIKU
references. Basically it’s just a way of namespacing objects to make them globally available. Try reading up on the YUI library for more information.
As always, feel free to post with any questions.
var MIKU;
/*
* Method to allow namespacing of new objects within MIKU;
*
* Example:
* MIKU.namespace('objectname');
* MIKU.objectname = function() { return {'...'} }
*
*/
MIKU = function() {
return {
namespace: function(name) {
try {
if (MIKU[name]) {
throw 'Namespace exists.';
}
return {}
}
catch (e) {
this.throwError(e);
}
}
}
}();
MIKU.namespace('throwError');
/*
* Method to catch MIKU errors
*/
MIKU.throwError = function(e) {
if (console) {
console.error((e.message || 'MikuError:'), e);
}
};
/*
* Init the JsonRpc namespace into the MIKU object.
*/
MIKU.namespace('JsonRpc');
/*
* Miku Json-RPC Implementation
*/
MIKU.JsonRpc = function() {
var _url = 'json-rpc/call';
var _timeout = false;
var _requests = [];
var _responses = [];
var _callbacks = {};
var _requestId = 0;
var _failures = 0;
function _send() {
_request();
_t = false;
_requests = [];
}
function _request() {
try {
if (!_url) {
throw('undefined post url.');
}
$.ajax({
type: 'POST',
url: _url,
data: ({
request: JSON.stringify(_requests)
}),
dataFilter: function(data, type) {
//check for php errors
try {
return JSON.parse(data);
}
catch (e) {
var phpError = /^.*?(Error|Warning|Notice).*?\:\s*(.*?) in .*?(\/[0-9A-Za-z\/\.\-\_\ ]+).* on line .*?([0-9]+).*$/i;
var lines = data.split(/\n/g);
$.each(lines, function() {
var error = this.match(phpError);
if (error) {
MIKU.throwError({
message: error[1] + ': ' + error[2],
file: error[3],
line: error[4]
});
}
});
}
},
success: function(data) {
_success(data);
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
// retry after connection failures
if (XMLHttpRequest.status != '200') {
_failures ++;
if (_failures < 3) {
_request();
return;
}
}
// give up and throw errors...
MIKU.throwError([XMLHttpRequest, textStatus, errorThrown]);
}
});
}
catch(e) {
MIKU.throwError(e);
}
}
function _success(response) {
$.each(jQuery.makeArray(response), function() {
try {
if (this.error) {
// check for error
throw(this.error);
}
else if(this.result) {
// trigger callback
var callback = _callbacks[this.id];
callback(this.result);
}
}
catch(e) {
MIKU.throwError(e);
}
});
// reset callbacks
_callbacks = {};
}
function _genId() {
return ++_requestId;
}
return {
version: '2.0',
delay: 10,
setUrl: function(url) {
_url = url;
},
call: function(args) {
var id = _genId();
var request = {
jsonrpc: this.version,
method: args.method,
params: args.params,
id: id
}
_requests.push(request);
_callbacks[id] = args.onSuccess;
if (_timeout) {
clearTimeout(_timeout);
}
_timeout = setTimeout(_send, this.delay);
return request;
}
}
}();
/*
* Testing Below
*/
$(document).ready(function() {
var rpc = MIKU.JsonRpc;
rpc.call({
method: 'System.getTitle',
params: [
'id_13'
],
onSuccess: function(result) {
console.debug(result);
}
});
});