本文介绍了AMD结构化网络应用中的Mixpanel 2.2-例如require.js的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在基于Backbone.js和require.js的单页站点中使用Mixpanel事件跟踪.

I'm attempting to make use of Mixpanel event tracking in a single page site based on Backbone.js and require.js.

查看Mixpanel提供的用于剪切和粘贴的片段进入常规网页,我可以知道他们已经采用了自己的异步加载机制,该机制可以引入实际的来自独立资源的Mixpanel API ,做一些额外的工作来设置人员"和其他属性,最后通过全局命名空间公开"mixpanel"对象.

Looking at the snippet that Mixpanel provide for cut-and-pasting into a regular webpage, I can tell they've rolled their own async loading mechanism that pulls in the actual Mixpanel API from a standalone resource, do some extra work to setup 'people' and other attributes, and finally expose the 'mixpanel' object through the global namespace.

我尝试为代码段或独立API添加填充程序配置条目,但都无法正常工作.

I've tried to add shim config entries for either the snippet or the standalone API but neither work well.

通过研究,我在github上找到了一个项目,它完全符合我的要求,但是它已经存在了几年并且基于旧" mixpanel API.在新版本中,Mixpanel对代码段和API进行了一些微不足道的更改,而这些只是我无法理解的.

Through my research, I found a project on github that does exactly what I want, however it's a few years old and is based on the 'old' mixpanel API. In the new version, Mixpanel have made some non-trivial changes to the snippet and API that I just can't get my head around.

我希望有人能理解Mixpanel片段和/或AMD,并且可以使用require.js,并能逐步引导我完成这一过程.

I'm hoping somebody understands the Mixpanel snippet and/or AMD and require.js and can step me through this.

推荐答案

有两个有趣的事情使这成为一个奇怪的问题要解决:

There are two funny things that makes this an odd problem to solve:

  1. mixpanel库要求您在加载窗口之前先定义window.mixpanel.
  2. mixpanel库重新定义window.mixpanel作为其初始化过程的一部分.

开箱即用,在加载lib之前,mixpanel代码段不支持get_distinct_id(以及根据定义,任何调用都是同步的),但是在加载mixpanel lib之前,不存根其他方法(例如track).为了排队.因此,我们有两个选择:

Out of the box, the mixpanel snippet doesn't support get_distinct_id (and any call that is, by definition, synchronous) until the lib is loaded but does stub out other methods (such as track) BEFORE loading the mixpanel lib for the sake of queueing. Therefore we have two options:

选项1.放弃异步支持,等待直到加载lib-要点

Option 1. Drop async support and wait until the lib is loaded - Gist

此方法通过创建一个预初始化模块来设置mixpanel库所需的window.mixpanel deps,然后将其指定为对库本身的依赖来工作.然后要求"mixpanel"将阻塞,直到lib完全加载为止.

This method works by creating a pre-init module to setup the window.mixpanel deps needed by the mixpanel lib and then specifying that as a dependency to the lib itself. Then requiring "mixpanel" will block until the lib is fully loaded.

<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.提供已加载"回调以更新模块的属性. -要点

Option 2. Provide a "loaded" callback to update the module's properties. - Gist

如果您确实需要异步支持,则在加载mixpanel库之后,需要更新存根的方法.我不建议这样做,因为(除其他原因外)它会在复制后导致window.mixpanel!== mixpanel.这也意味着您必须在诸如get_distinct_id()之类的同步调用上防止竞争条件.如果尚未加载该库,则它将是未定义的.注意:我建议,如果您必须具有异步支持,则应仅通过window.mixpanel进行调用,而不要通过所有这些疯狂方式进行调用.

If you REALLY want async support, you'll need to update your stub's methods once the mixpanel lib is loaded. I don't recommend this because (among other reasons) it results in window.mixpanel !== mixpanel after the copy. This also means you must protect against race conditions on synchronous calls like get_distinct_id(). If the lib hasn't loaded yet, it'll be undefined. NOTE: I recommend that if you must have async support, you should just call through window.mixpanel instead of all of this craziness.

<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>

这篇关于AMD结构化网络应用中的Mixpanel 2.2-例如require.js的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-24 11:36