将回调函数作为字符串传递,同时保留作用域链

Posted

技术标签:

【中文标题】将回调函数作为字符串传递,同时保留作用域链【英文标题】:Passing a callback function as a string while retaining the scope chain 【发布时间】:2011-06-28 13:26:22 【问题描述】:

对于使用 UIWebView 的 iPad 应用,我在 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;    

应用从 URL 解析回调函数,并通过 stringByEvaluatingjavascriptFromString 插入一些数据来调用回调函数。这一切都很好。

但是,现在我想在回调函数中使用闭包,如下所示:

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

这是有问题的。由于回调函数被转换为字符串,所有作用域链信息都丢失了。

关于如何解决这个问题有什么建议吗?

编辑:

我更喜欢“查询”功能方面的解决方案。例如:有什么方法可以将作用域链中的变量转换为 eval()-able 字符串?

【问题讨论】:

如果您在iPhone WebDev group 上提问,您可能会更快得到答案。 好建议,谢谢! 【参考方案1】:

除了将回调函数本身传递给查询页面之外,您能不传递一个与回调数组中的索引对应的 ID 吗?

例如

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

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

现在,您为查询 iframe src 提供回调索引而不是实际的回调函数

最后,您的查询服务器端脚本可以返回类似于

的内容
callbacks[0]("this is a load of JSON for example");

【讨论】:

不过,这确实需要您控制服务器端脚本。 问题是回调被异步调用,并且可以同时有多个“正在运行”的多个任务。我可以使用全局变量来存储函数,甚至只是'problemData',但这将我的问题转移到访问数组中的正确索引,该数组存储正确的数据以进行正确的回调。 @TumbleCow 您可以通过将回调的索引传递给服务器来解决这个问题。然后服务器可以返回一个实际上是 Javascript 的字符串。例如,如果您使用以下 URL http://example.com/myqueryscript?q=MyQuery&callbackID=0 调用查询脚本,则查询脚本将返回 callbacks[0]("this is a load of JSON for example"); 其中“0”是来自查询字符串 callbackID 的值。如果这样做,您可以异步调用任意数量的查询。只需将正确的 ID 传递给查询脚本【参考方案2】:
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);

但在我看来,像这样使用 Function 构造函数并不是很好 =)。 https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function

【讨论】:

以上是关于将回调函数作为字符串传递,同时保留作用域链的主要内容,如果未能解决你的问题,请参考以下文章

通过 Angular 模板传递回调函数时保留此上下文

理解回调函数

js判定是不是传入回调函数

回调函数(callback)是啥? ,,

将回调函数作为道具传递给孩子

将 Go 函数作为回调传递给 C