有两件有趣的事情使这个问题变得很奇怪:
- mixpanel 库要求您在加载它之前定义 window.mixpanel。
- mixpanel 库将 window.mixpanel 重新定义为它的 init 进程的一部分。
开箱即用,mixpanel 片段在加载 lib 之前不支持 get_distinct_id (以及根据定义,同步的任何调用),但在加载 mixpanel lib 之前会存根其他方法(例如跟踪)排队。因此我们有两种选择:
选项 1. 放弃异步支持并等待库加载 -要点
此方法通过创建一个预初始化模块来设置 mixpanel lib 所需的 window.mixpanel 依赖项,然后将其指定为对 lib 本身的依赖项。然后要求“mixpanel”将阻塞,直到库完全加载。
<html>
<head>
<title>Mixpanel AMD Example - Sync</title>
<script type="text/javascript" src="http://requirejs.org/docs/release/2.1.8/minified/require.js"></script>
<script type="text/javascript">
requirejs.config({
paths : { 'mixpanel': "//cdn.mxpnl.com/libs/mixpanel-2.2.min" },
shim: {
'mixpanel': {
deps: ['mixpanel-preinit'],
exports: 'mixpanel'
}
}
});
define("mixpanel-preinit", function(require) {
// this is a stripped down version of the mixpanel snippet that removes the loading of the lib via external script tag and the stubs for queuing calls
var b=window.mixpanel=window.mixpanel||[];var i,g;b._i=[];b.init=function(a,e,d){function f(b,h){var a=h.split(".");2==a.length&&(b=b[a[0]],h=a[1]);b[h]=function(){b.push([h].concat(Array.prototype.slice.call(arguments,0)))}}"undefined"!==typeof d?c=b[d]=[]:d="mixpanel";b._i.push([a,e,d])};b.__SV=1.2;
b.init("YOUR TOKEN");
});
</script>
</head>
<body>
<script type="text/javascript">
require(['mixpanel'], function(mixpanel) {
mixpanel.track("my event", {prop1: "val1"});
console.log(mixpanel.get_distinct_id());
});
</script>
</body>
</html>
选项 2. 提供“加载”回调来更新模块的属性。-要点
如果您真的需要异步支持,则需要在加载 mixpanel 库后更新存根的方法。我不推荐这样做,因为(除其他原因外)它会在复制后导致 window.mixpanel !== mixpanel。这也意味着您必须防止像 get_distinct_id() 这样的同步调用出现竞争条件。如果该库尚未加载,它将是未定义的。注意:我建议如果你必须有异步支持,你应该只通过 window.mixpanel 调用而不是所有这些疯狂。
<html>
<head>
<title>Mixpanel AMD Example - Async</title>
<script type="text/javascript" src="http://requirejs.org/docs/release/2.1.8/minified/require.js"></script>
<script type="text/javascript">
requirejs.config({
paths : { 'mixpanel-lib': "//cdn.mxpnl.com/libs/mixpanel-2.2.min" }
});
define("mixpanel", function(require) {
var b = window.mixpanel || [];
if (!b.__SV) { var i, g; window.mixpanel = b; b._i = []; b.init = function (a, e, d) { function f(b, h) { var a = h.split("."); 2 == a.length && (b = b[a[0]], h = a[1]); b[h] = function () { b.push([h].concat(Array.prototype.slice.call(arguments, 0))) } } var c = b; "undefined" !== typeof d ? c = b[d] = [] : d = "mixpanel"; c.people = c.people || []; c.toString = function (b) { var a = "mixpanel"; "mixpanel" !== d && (a += "." + d); b || (a += " (stub)"); return a }; c.people.toString = function () { return c.toString(1) + ".people (stub)" }; i = "disable track track_pageview track_links track_forms register register_once alias unregister identify name_tag set_config people.set people.set_once people.increment people.append people.track_charge people.clear_charges people.delete_user".split(" "); for (g = 0; g < i.length; g++) f(c, i[g]); b._i.push([a, e, d]) }; b.__SV = 1.2 }
// go ahead and start loading the mixpanel-lib
require(['mixpanel-lib']);
b.init("YOUR TOKEN", {loaded: function() {
// now that we know mixpanel is loaded, copy the prop references to our module def
for(var prop in window.mixpanel) {
b[prop] = window.mixpanel[prop];
}
}});
return b;
});
</script>
</head>
<body>
<script type="text/javascript">
require(['mixpanel'], function(mixpanel) {
mixpanel.track("my event", {prop1: "val1"});
console.log(mixpanel.get_distinct_id()); // probably undefined
});
</script>
</body>
</html>