0

In my web app I inject some user specific data into the html page.

It looks like this in the page source

<body>
<script>

      var userData = {};
      window.GLOBAL = {
        userData: userData
      };
      userData.user = {'user_hash': 12478999584505 };
</script>
<script  src="/static/scripts/myapp.js"> </script>

Inside myapp.js I retrieve the user_hash and call an initialisation function:

 init(window.userData.user.user_hash);

A few users experience this problem spuriously:

Cannot read property 'user_hash' of undefined

It turns out it is very hard for me to pinpoint the exact cause of the problem. This error never happen to me in either production or development environment. There is also no error on the server side that indicates the user_hash generation has failed. I have tried to reproduce this error by throttling network speed in Chrome via Dev Console etc but I haven't been able to trigger this error yet.

On the user side, the platforms vary from mobile devices (could be running the latest version of iOS or andriod) to desktop, and different browsers (chrome, firefox or safari). My point is there is no clear pattern I can pin it down to a particular platform or brower version.

I speculate that the exception happens if /static/scripts/myapp.js is loaded and executed before window.GLOBAL is properly initialised, this exception will be fired.

I am thinking of adding defer keyword to the myapp.js script tag, based on this answer.

My questions are:

1) Is there any issue with my current HTML markup? (the two script tags)

2) My hypothesis is basically that these two script tags may have some racing condition between them. Does it stand?

3) Can adding defer attribute to the second script tag potentially fix this issue if answer to question 2 is yes?

4) If answer to question 3 is no, what else I can try?

Anthony Kong
  • 37,791
  • 46
  • 172
  • 304
  • Is `user` property actually named `"user"`? The first script should define the properties before the second script is executed. Can you reproduce the issue at plnkr https://plnkr.co? – guest271314 Nov 06 '17 at 01:39
  • Do you mean the `defer` *attribute* for the `script` tag? It's not a keyword. But no, adding it won't help anything here. – Bergi Nov 06 '17 at 02:30
  • It seems more likely that something else in your code is messing with the `GLOBAL.user` object. – Bergi Nov 06 '17 at 02:31
  • @AnthonyKong Can you tell me does my answer make sense to you or not? – Dipak Nov 06 '17 at 03:46
  • @Dipakchavda Thanks for a very detailed answer – Anthony Kong Nov 06 '17 at 03:52
  • @AnthonyKong I thankful to you that my answer makes sense to you like senior guy in stackoverflow. – Dipak Nov 06 '17 at 03:55

1 Answers1

1

1) Is there any issue with my current HTML markup? (the two script tags)

No there is no issue with HTML markup.

2) My hypothesis is basically that these two script tags may have some racing condition between them. Does it stand?

I did not get this question perfectly. Probably you should show your myapp code here

3) Can be adding defer attribute to the second script tag potentially fix this issue if answer to question 2 is yes?

No. JavaScript is always synchronous and single-threaded. If you're executing a JavaScript block of code on a page then no other JavaScript on that page will currently be executed. JavaScript is only asynchronous in the sense that it can make, for example, Ajax calls. and Defer instructs the contents of the script tag to not execute until the page has loaded.

4) If the answer to question 3 is no, what else I can try?

You don't require to use GLOBAL here because when you initialize variable with var on top of the script then it may automatically consider in a global scope. JavaScript has two scopes: global and local. A variable that is declared outside a function definition is a global variable, and its value is accessible and modifiable throughout your program. A variable that is declared inside a function definition is local, and second thing window object represents. the browser's window. All global JavaScript objects, functions, and variables automatically become members of the window object.

Here following code may fulfil your requirement

var userData = {
   userData: userData
 };
 userData.user = {'user_hash': 12478999584505 };

 console.log(userData.user.user_hash);

Here is also link of working fiddle: https://jsfiddle.net/dipakchavda2912/eohb0npr/

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Dipak
  • 2,248
  • 4
  • 22
  • 55