0

概述

所以我编写了一个 Video.js 插件,它可以向谷歌分析和我们的自定义报告报告。

我们发送回页面的每个 JSONP 请求都使用 encodeURIComponent 使用此方法进行编码。前几个正确开火。然后它开始出错TypeError: '[object Object]' is not a function (evaluating 'encodeURIComponent(p)')。这只发生在 Safari 中。(我在 OSX Mavericks 上使用 safari 7.0.1)

我什至尝试过使用整个 url 字符串,encodeURI但同样的事情也发生在该函数上。

我创建了一个 [JS FIDDLE][2] 来演示这个问题。我只用一些示例代码重新创建它没有成功,所以我已经将所有相关文件包含在外部资源中。如果它不这样做,请在大约 85% 的时间里重新运行它发生在我身上的页面。

遍历函数

我首先添加要跟踪的事件

this.on('play',onPlay);
this.on('pause',onPause);

当一个事件触发时,它会被这些函数捕获

function onPlay( e ) {
    videoData = getVideoData();
    doTracking({
        'category': videoData.cid,
        'action': videoData.vid,
        'label': 'Play',
        'value': null
    });
}

function onPause( e ) {
    videoData = getVideoData();
    doTracking({
        'category': videoData.cid,
        'action': videoData.vid,
        'label': 'Pause',
        'value': getTime()
    });
}

从哪个获取视频数据

function getVideoData() {
    var src = videojsRef.player().currentSrc();
    var srcSplit = src.split('/');

    var filename = srcSplit[srcSplit.length-1];
    var filenameSplit = filename.split('.');

    var cid = filenameSplit[0];
    var vid = filenameSplit[1];
    var type = filenameSplit[2];

    var returnObj = {
        'cid': cid,
        'vid': vid,
        'filename': filename
    };

    return returnObj;
}

然后调用“doTracking”,它只是一个调用两个跟踪函数的辅助函数。

function doTracking( opt ) {

    if ( gaType && bvReady ) { // Are both tracking types initialized
        // Send to google
        googleTrack( opt );

        // Send to BetterVideo
        bvTrack( opt );
    } else {
        queue.push( opt );
    }
}

哪个调用 bvTrack(opt)

function bvTrack( opt ) {
    var args = {
        pid: playerid,
        cid: opt.category,
        vcd: opt.action,
        a: opt.label,
        callback: '{callback}'          
    };

    if ( opt.value !== null ) {
        args.val = opt.value;
    }

    // Heres where the trouble starts
    new videojs.JSONP('http://jsfiddle.net/echo/jsonp/?'+serializeToQuery(args), function( response ) {
        console.log('[BV Reporting] Tracking Response: ', arguments );
    })
}

数据在这里被序列化

function serializeToQuery( obj ) {
    var str = [];
    console.log( "serializeToQuery", obj );
    for(var p in obj) {

        if ( obj.hasOwnProperty(p) ) {
            console.log( '    property', p, obj[p]);
            console.log( '        encodeURIComponent', typeof encodeURIComponent == 'function' ? 'function' : encodeURIComponent );
            console.log( '        encoded property', encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
            str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p])); 
        }
    }   
    return str.join("&");
}

然后传递给d3.js 启发的 JSONP(我相信我在这里找到了 SO

videojs.JSONP = function (url, callback) {
    var docHead = document.getElementsByTagName('head')[0];
    function rand() {
        var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
        c = '', i = -1;
        while (++i < 15) c += chars.charAt(Math.floor(Math.random() * 52));
        return c;
    }

    function create(url) {
        var e = url.match(/callback=jsonp.(\w+)/),
        c = e ? e[1] : rand();
        videojs.JSONP[c] = function(data) {
            callback(data);
            delete videojs.JSONP[c];
            docHead.removeChild(script);
        };
        return 'videojs.JSONP.' + c;
    }

    var cb = create(url),
        script = document.createElement('script');
        script.type = 'text/javascript';
        script.src = url.replace(/(\{|%7B)callback(\}|%7D)/, cb);
        docHead.appendChild(script)
};

输出

serializeToQuery Object { 
                            a: "Pause"
                            callback: "{callback}"
                            cid: "oceans"
                            pid: "885FA551-A873-4BB9-891A-ABC08CD47D36"
                            val: 6
                            vcd: "mp4"
                        }
    property pid 885FA551-A873-4BB9-891A-ABC08CD47D36
        encodeURIComponent function
        encoded property pid=885FA551-A873-4BB9-891A-ABC08CD47D36
    property cid oceans
        encodeURIComponent function
        encoded property cid=oceans
    property vcd mp4
        encodeURIComponent function
        encoded property vcd=mp4
    property a Pause
        encodeURIComponent function
        encoded property a=Pause
    property callback {callback}
        encodeURIComponent function
        encoded property callback=%7Bcallback%7D
    property val 6
        encodeURIComponent function
        encoded property val=6

但在 2 或 3 次 JSONP 调用之后,它会输出以下内容:

serializeToQuery Object {
                            a: "Play"
                            callback: "{callback}"
                            cid: "oceans"
                            pid: "885FA551-A873-4BB9-891A-ABC08CD47D36"
                            vcd: "mp4"
                        }

    property pid 885FA551-A873-4BB9-891A-ABC08CD47D36 
        encodeURIComponent  Object {
                                        cid: "oceans"
                                        filename: "oceans.mp4"
                                        vid: "mp4"
                                    }

[Error] TypeError: '[object Object]' is not a function (evaluating 'encodeURIComponent(p)')
    serializeToQuery (videojs.bvReporting.js, line 531)
    bvTrack (videojs.bvReporting.js, line 481)
    doTracking (videojs.bvReporting.js, line 329)
    onPlay (videojs.bvReporting.js, line 113)
    ret (video.dev.js, line 769)
    dispatcher (video.dev.js, line 295)
    trigger (video.dev.js, line 529)
    trigger (video.dev.js, line 1868)
    eventHandler (video.dev.js, line 5376)
    ret (video.dev.js, line 769)
    dispatcher (video.dev.js, line 295)

如您所见encodeURIComponent,现在是调用它的最后一个对象。

有任何想法吗?

4

1 回答 1

0

在每个跟踪事件侦听器中都有/videoData = getVideoData() 曾经我添加varvideoData问题停止。有谁知道为什么这可能是原因?我知道它被设置为全局变量,但 encodeURIComponent 是如何设置为对象的?

于 2014-02-11T15:53:46.477 回答