更改window.location / document.location后PhoneGap如何保持Javascript执行

时间:2012-09-03 13:32:49

标签: javascript ios cordova uiwebview webview

根据this question,当我们设置window.location时,javascript将“停止”执行或变成竞争条件。

有时我们需要在WebView中多次触发window.location = SOMESCH://xxx以将“通知”发送回我们的应用程序。例如,设置window.location = myapp://loginButtonEnabled?e=1告诉应用程序用户填写了一些nessasary信息并可以开始登录。似乎不可能做这样的事情:

function(){
window.location = myapp://loginButtonEnable?e=1;
window.location = myapp://hideHintView;
.....
window.location = myapp://theLastThing;
}

只会触发最后一个window.location = myapp://theLastThing,然后Javascript的执行将停止(尽管我们通过在webView:shouldStartLoadWithRequest:navigationType:中返回NO来停止在我们的应用中重定向。)

我觉得有趣的是,PhoneGap通过使用调度队列使这成为可能,但我仍然不知道它为什么有效,任何人都知道这个技巧?

顺便说一下,设置位置后有没有简单的方法来“恢复”执行?它比使用操作队列要好得多。

1 个答案:

答案 0 :(得分:5)

您需要为事件循环提供每次响应位置更改的机会。这样做的典型方法是使用具有小/零延迟的setTimeout,这具有将执行移动到下一个事件循环滴答的效果。尝试这样的事情:

var q=[];

function dequeue() {
  window.location='myapp://'+q.shift();
  if (q.length>0) setTimeout(dequeue,0);
}

function notifyApp(cmd) {
  q.push(cmd);
  if (q.length==1) setTimeout(dequeue,0);
}

notifyApp('loginButtonEnable?e=1');
notifyApp('hideHintView');
notifyApp('theLastThing');

至于javascript执行停止,设置window.location不应该有此效果,除非它实际导致页面更改 - 也许尝试使用上面的技术,看看你的javascript是否在最后notifyApp()之后继续调用

编辑:此问题的另一种方法是创建临时iframe而不是更改当前页面的位置 - 例如,请参阅 Triggering shouldStartLoadWithRequest with multiple window.location.href calls