概述
所以我编写了一个 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
,现在是调用它的最后一个对象。
有任何想法吗?