The simple AJAX function we're using has a an event handler that we use to deal with intermittent network problems. Instead of having the script bomb out when the server is busy, we want it to wait a few moments, then try the call again.
Part of the problem with this is that by the time our script has picked up the error, it has already moved on to other things, so the object that we used to set the server request variables is no longer available. How do you pass these "retry" parameters to an onError event handler that is called from a setTimeout() function?
The method I came up with is quite the eclectic mix of code. What we need to do is take the object that contains all our parameters and convert it to a string so that we can pass it back to the AJAX function as a regular parameter. This is how I've done it:
// Function converts a JSON object to string literal for passing
// into externally referenced callbacks (a la on AJAX failure retries)
Object.prototype.toJSON = function () {
// We first need to declare an array to hold each propertyName/value pair
var result = [];
// Now iterate through each property and assign them to the array
for(var element in this){
var key;
var val;
// Prepare the object property names...
// encapsulate strings in quotes,
// let numbers go unscathed,
// recurse if it's an embedded object,
// skip everything else
if (typeof element == "string") {
key = "'" + element + "'";
} else if (typeof element == "number") {
key = element;
} else if (typeof element == "object") {
key = element.toJSON();
} else {
continue;
}
// Do the same for the object values
if(typeof this[element] == "string"){
val = "'" + this[element] + "'";
} else if (typeof this[element] == "number") {
val = this[element];
} else if (typeof this[element] == "object") {
val = this[element].toJSON();
} else {
continue;
}
// Add the most recent name/value pair to the result array
result.push(key + ":" + val);
}
// Send the properly formatted string back to the script
// We do this by concatenating the elements together into a string
result = "{ " + result.join(", ") + " }";
return(result);
};
For the uninitiated, this is a method prototype extension. It works just like a .toString() call would. For example:
var testObj = { 'var1':0, 'var2':'sampleText', 'var3':12345 };
var testStr = testObj.toJSON();
The testStr variable now holds the contents of testObj, but as a string literal, so that we can pass it around wherever (or, more accurately, whenever) we want.
Again, I'm sure there's a lot of room for improvement here, but it serves the purpose we need, so I'm not going to beat myself up if someone shows me a cleaner way.
I have seen a couple alternatives that rely on a completely different approach, but I have yet to try them (partly because it appears that using them would require a significant review of our AJAX functions).
What I like most about this little method is that it's smart enough to handle nested objects. What I don't like is that it's long, and easily bombs out if the object being referenced is not a true object (but instead, say, a string variable). This is something I could fix in the future, but I would instead just say, "Don't do that!" (Because it means less work for me.) :)
(Note: the tabs for indentation don't turn out real well here. I'll have to find a fix for that.)