0

For an iPad app using a UIWebView, I'm passing a callback function to the app in an URL:

function query(db, query, callback) {
  var iframe = document.createElement("IFRAME");

  // Filter comments from the callback (as this would break things).
  var callbackstr = "" + callback;
  callbackstr = callbackstr.replace(/\/\*.+?\*\/|\/\/.*(?=[\n\r])/g, ''); 

  // Put the query + the callback in an url that will be caught by the iOS app. 
  iframe.setAttribute("src", "ios-query:#iOS#" + query +":#iOS#"+ callbackstr);
  document.documentElement.appendChild(iframe);
  iframe.parentNode.removeChild(iframe);
  iframe = null;    
}

The app parses the callback function from the URL, and calls the callback function with some data inserted through stringByEvaluatingJavaScriptFromString. This is all working fine.

However, now I want to use a closure in the callback function, like so:

            var callback = function (problemdata) {
                // Return the 'real' callback.
                return function (tx, results) {
                    // Do something with problemdata
                }
            }(problemdataFromScopeChain)

This is problematic. Since the callback function gets converted to a string, all scope-chain information is lost.

Any suggestions on how to solve this problem?

edit:

I would prefer a solution on the side of the 'query' function. For example: Is there any way to convert the vars in the scope-chain to an eval()-able string?

TinkerTank
  • 5,685
  • 2
  • 32
  • 41
  • You might get an answer sooner if you ask on the [iPhone WebDev group](https://groups.google.com/group/iphonewebdev/topics?hl=en). – RobG Jun 28 '11 at 13:51

2 Answers2

3

Instead of passing the callback function itself to the query page, could you not pass an ID that coresponds to an index in an array of callbacks?

for example

var callback = function(problemdata){
// Do stuff
};

callbacks = [];
callbacks.append(callback); // so index of 0

Now, you supply the query iframe src with the callback index instead of the actual callback function

finally, your query server side script can return something along the lines of

callbacks[0]("this is a load of JSON for example");
  • Although, this does require that you have control of the server side script. – Tim Fletcher Jun 28 '11 at 14:28
  • The problem is that the callbacks are being called asynchronously, and that there can be multiple multiple tasks 'in flight' at the same time. I can use a global var to store the function, or even just the 'problemData', but that moves my problem to accessing the right index in the array that is storing the right data for the right callback. – TinkerTank Jun 29 '11 at 08:14
  • @TumbleCow You can overcome this issue by passing the index of the callback to the server. The server can then return a string that is actually Javascript. For example, if you call the query script with the following URL `http://example.com/myqueryscript?q={MyQuery}&callbackID=0` The query script would return `callbacks[0]("this is a load of JSON for example");` Where '0' is the value from the querystring callbackID If you do this, you can call any number of queries asynchronously. just pass the correct ID to the query script – Tim Fletcher Jun 29 '11 at 09:26
0
var problemdataFromScopeChain = 4;
var callback = function(problemdata){
  // Return the 'real' callback.
  //return function (tx, results) {
  //  // Do something with problemdata
  //  return tx + results + problemdata;
  //}
  return new Function('tx', 'results', 'return tx + results + ' + problemdata + ';');
}(problemdataFromScopeChain);
alert('' + callback);

But in my opinion using the Function constructor like this is not very nice =). https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function

Prusse
  • 4,287
  • 2
  • 24
  • 29