在我的网络应用程序中,我将一些用户特定数据注入到html页面中。
在页面源
中看起来像这样<body>
<script>
var userData = {};
window.GLOBAL = {
userData: userData
};
userData.user = {'user_hash': 12478999584505 };
</script>
<script src="/static/scripts/myapp.js"> </script>
在myapp.js
内我检索user_hash
并调用初始化函数:
init(window.userData.user.user_hash);
一些用户虚假地遇到了这个问题:
Cannot read property 'user_hash' of undefined
事实证明,我很难确定问题的确切原因。在生产或开发环境中,这个错误永远不会发生在我身上。服务器端也没有错误表明user_hash
代已失败。我试图通过Dev Console等在Chrome中限制网络速度来重现此错误,但我还没有能够触发此错误。
在用户方面,平台各不相同,从移动设备(可以运行最新版本的iOS或andriod)到桌面,以及不同的浏览器(chrome,firefox或safari)。我的观点是没有明确的模式我可以将其固定到特定的平台或更广泛的版本。
我推测如果在/static/scripts/myapp.js
正确初始化之前加载并执行window.GLOBAL
,则会发生异常,此异常将被触发。
我正在考虑将defer
关键字添加到myapp.js
脚本代码based on this answer。
我的问题是:
1)我目前的HTML标记有问题吗? (两个脚本标签)
2)我的假设基本上是这两个脚本标签可能在它们之间有一些竞争条件。它有效吗?
3)如果对问题2的回答是肯定的,可以向第二个脚本标记添加defer
属性可能会解决此问题吗?
4)如果问题3的回答是否定的,我还能尝试什么?
答案 0 :(得分:1)
1)我目前的HTML标记有问题吗? (两个脚本标签)
HTML标记没有问题。
2)我的假设基本上是这两个脚本标签可能在它们之间有一些竞争条件。它有效吗?
我没有完全理解这个问题。您可能应该在此处显示您的myapp代码
3)如果对问题2的回答是肯定的,可以将defer属性添加到第二个脚本标记可能会解决此问题吗?
没有。 JavaScript始终是同步和单线程的。如果您在页面上执行JavaScript代码块,则当前不会执行该页面上的其他JavaScript。从某种意义上说,JavaScript只能是异步的,例如,它可以进行Ajax调用。和Defer指示脚本标记的内容在页面加载之前不执行。
4)如果问题3的答案为否,我还能尝试什么?
您不需要在此处使用GLOBAL,因为当您在脚本顶部使用var初始化变量时,它可能会在全局范围内自动考虑。 JavaScript有两个范围:全局和本地。在函数定义之外声明的变量是全局变量,其值可在整个程序中访问和修改。在函数定义中声明的变量是本地的,第二个窗体对象表示。浏览器的窗口。所有全局JavaScript对象,函数和变量都自动成为窗口对象的成员。
以下代码可能符合您的要求
var userData = {
userData: userData
};
userData.user = {'user_hash': 12478999584505 };
console.log(userData.user.user_hash);
这里也是工作小提琴的链接:https://jsfiddle.net/dipakchavda2912/eohb0npr/