2

According to this question, when we set the window.location, javascript will "stop" executing or turn into a race condition.

Sometimes we need to fire window.location = SOMESCH://xxx multiple times inside a WebView to send "Notifications" back to our app. For example setting window.location = myapp://loginButtonEnabled?e=1 to tell the app that the user had filled in some nessasary info and can start login. It seems to be impossible to do something like this:

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

Only the last window.location = myapp://theLastThing will be fired and then the execution of Javascript will stop(though we stopped the redirecting in our app by returning NO in webView:shouldStartLoadWithRequest:navigationType:).

I found it interesting that PhoneGap made this possible by using a dispatching queue, but I still haven't figure out why it works, anybody knows the trick??

BTW, is there a simple way to "resume" the execution after setting location? It will be much better than using an operation queue.

Community
  • 1
  • 1
PeakJi
  • 1,547
  • 14
  • 23

1 Answers1

5

You need to give the event loop a chance to respond to the location change each time. The typical way of doing this is using a setTimeout with a small/zero delay, which has the effect of moving execution to the next event loop tick. Try something like this:

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');

As for javascript execution stopping, setting window.location shouldn't have this effect unless it actually results in a page change - perhaps try using the technique above and see if your javascript continues after the last notifyApp() call.

EDIT: Another approach to this issue is to create temporary iframes instead of changing the location of the current page - see for example Triggering shouldStartLoadWithRequest with multiple window.location.href calls

Community
  • 1
  • 1
CupawnTae
  • 14,192
  • 3
  • 29
  • 60