Es gibt zwei lustige Dinge, die dieses eine ungerade Problem macht zu lösen:
- Die mixpanel lib erfordert, dass Sie window.mixpanel definiert haben, bevor Sie es laden.
- Die Mixpanel-Bibliothek definiert window.mixpanel als Teil ihres Init-Prozesses neu.
Aus dem Kasten, die Schnipsel mixpanel nicht get_distinct_id (und jeden Anruf, der per Definition ist, synchron) unterstützen, bis die lib geladen, aber nicht andere Verfahren Stub (wie Spur), bevor die Lade mixpanel lib um der Warteschlange willen. Deshalb haben wir zwei Möglichkeiten:
Option 1. Tropfen Asynchron-Unterstützung und warten, bis die lib geladen wird - Gist
Diese Methode funktioniert durch eine Pre-init-Modul zur Einrichtung der Erstellung der window.mixpanel deps benötigt durch die mixpanel lib und dann das als eine Abhängigkeit zu der lib selbst angeben. Dann wird "mixpanel" benötigt, bis die lib vollständig geladen ist. 2.
<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>
Option Geben Sie einen "geladen" Rückruf des Moduls Eigenschaften zu aktualisieren. -
Wenn Sie wirklich async Unterstützung möchten, müssen Sie die Methoden Ihres Stubs aktualisieren, sobald die Mixpanel-Bibliothek geladen ist. Ich empfehle das nicht, weil es (neben anderen Gründen) window.mixpanel! == mixpanel nach der Kopie ergibt. Dies bedeutet auch, dass Sie sich bei synchronen Aufrufen wie get_distinct_id() gegen Race Conditions schützen müssen. Wenn die lib noch nicht geladen wurde, ist sie nicht definiert. Hinweis: Ich empfehle, wenn Sie Async-Unterstützung haben müssen, sollten Sie einfach durch window.mixpanel anstelle all dieser Verrücktheit aufrufen.
<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>
Dies (der erste Ansatz) funktioniert für mich - danke eine Tonne. –
Wir verwendeten einen sehr ähnlichen Ansatz zur zweiten Methode, mit dem Zusatz eines Versprechens, das sich löst, wenn das Mischpanel unseren "geladenen" Rückruf aufruft. Danke für die Hilfe! – liquidki
Option 1. funktionierte gut für mich, bis ich meinen Code durch den RequireJS-Optimierer lief. Die optimierte Ausgabe enthält den Mixpanel-Lib-Code mit einer angehängten Shim-Modul-Definition: define ("mixpanel", ["mixpanelPreInit"], (Funktion (global) {....} (this))); Leider wird der Mixpanel-Lib-Code immer noch ausgewertet, noch bevor die Moduldefinition ist. Wenn es ausgewertet wird, erwartet es, dass der Initialisierungscode bereits ausgeführt wurde. – tnunamak