Search code examples
javascriptreactjsinternet-explorer-11race-condition

IE 11 window.open() with javascript script loading race condition issue


Goal:

I have a ReactJs web app called "ImageGallery" that's currently integrated in our business suite system(which is a huge system contains older technologies, mainly web forms). In our system, we need to add a button to launch a browser window to spin the app.

ImageGallery app rely on the current system to pass data to it to show, which means, when the ImageGallery app loads, it calls a function on the business suite system side like

window.parent.loadData()

Since the data is passed in by JavaScript, there is no ajax call.

Code:

function showImage() {
    var imageGalleryWindow = window.open('/ImageGallery', '_blank', 'height=' + window.screen.availHeight + ',width=' + window.screen.availWidth + ',scrollbars=yes,menubar=no,resizable=yes,toolbar=no,location=no,status=no');
    imageGalleryWindow.loadData= loadData;
}

loadData() function is available on the current JavaScript file and will be passed to the new window so it can be used by the ReactJS app.

Problem:

The app works perfectly with Chrome/Firefox/Edge, but not IE 11. IE 11 sometimes loads, sometimes not. After taking a closer look, I found there's a race condition.

Basically whenever the app failed, loadData() function has not been passed to the newly created window. Again, that's only for IE11, all other browsers seems fine.

What I've tried:

I tried the following:

1> Tried to put a wait function in ImageGallery app like this:

static resolveDocuments(){
    if(typeof window.parent.loadData === 'function'){
      // do the work to show image
    } else {
      setTimeout(this.resolveDocuments, 2000);
    }
  }

I am using redux thunk, I didn't get any luck in getting this to work.

2> put imageGalleryWindow.loadData= loadData; into window.onload(), bad idea but tried anyways

3> put imageGalleryWindow.loadData= loadData; into imageViewerWindow.document.addEventListener("DOMContentLoaded", function (event) {} still bad idea but tried anyways

4> created a new ImageGallery.html, use an iframe to host ImageGallery app. In section, include the JavaScript file from parent. No luck

5> created a webform page ImageGallery.aspx, use an iframe to host ImageGallery app. In section, include the JavaScript file from parent. No luck.

Thanks for taking time to finish reading this problem, and please let me know if you have an idea I can try.

Thanks so much!

Ray


Solution

  • The solution I end up having is html 5 local storage:

    1. Before calling window.open() to populate the new window, create a entry in html 5 local storage with all the data I need to pass in.

    2. When the image gallery app loads, check if local storage items exists, if so, pull the data. The data will always be there, since it sets before new window generated, and since both pages are from the same domain, they could both access the same local storage.

    3. To avoid security issues, after image gallery app read data from the local storage, I keep a copy of the data within the app, then delete the local storage entry.

    Hope this can be helpful to other people.