[英]How to use segment.io's analytics.js in a knockout custom bindings
我正在使用淘汰赛为analytics.track进行自定义绑定,但似乎遇到了麻烦。 如果analytics.track嵌套在两个以上的函数中,则跟踪调用会以静默方式失败。 它不会触发回调,也不会在段调试器中报告。 我提供了2个示例来演示此问题:
不关闭(有效):
function sendTrack(event, props) {
console.log("Enter sendTrack");
analytics.track('Signed Up', {
plan: 'Enterprise'
}, {}, function () {
console.log('track callback logged');
});
}
ko.bindingHandlers.segmentTrack = {
init: function (element, valueAccessor) {
console.log("Init");
var value = ko.unwrap(valueAccessor());
ko.applyBindingsToNode(element, { click: sendTrack });
}
};
ko.applyBindings({});
有关闭功能(无效):
(function(ko, $, analytics){
'use strict';
function sendTrack(event, props) {
console.log("Enter sendTrack");
analytics.track('Signed Up', {
plan: 'Enterprise'
}, {}, function () {
console.log('track callback logged');
});
}
ko.bindingHandlers.segmentTrack = {
init: function (element, valueAccessor) {
console.log("Init");
var value = ko.unwrap(valueAccessor());
ko.applyBindingsToNode(element, { click: sendTrack });
}
};
ko.applyBindings({});
})(window.ko, window.jQuery, window.analytics);
Edit1:另外请注意,如果我将analytics.track移至init,则此方法适用:
(function(ko, $, analytics){
'use strict';
ko.bindingHandlers.segmentTrack = {
init: function (element, valueAccessor) {
console.log("Init");
analytics.track('Signed Up', {
plan: 'Enterprise'
}, {}, function () {
console.log('track callback logged');
});
}
};
ko.applyBindings({});
})(window.ko, window.jQuery, window.analytics);
请指教
这很可能是由于在window
对象上加载/初始化事物的顺序。 由于iife 立即执行,因此将analytics
变量设置为任何window.analytics
,即浏览器遇到iife的那一刻 。 在第一种情况下, 运行代码时将解析window.analytics
。
换句话说:闭包在执行iife时将捕获的window.analytics
捕获到作用域analytics
变量中 。
这是演示问题的演示。
不关闭:
function sendTrack() { console.log("Tracking..."); analytics.track("stuff"); } ko.bindingHandlers.segmentTrack = { init: function(element) { console.log("Init"); ko.applyBindingsToNode(element, { click: sendTrack }); } } ko.applyBindings({ }); // Simulate loading analytics now: window.analytics = { track: function(txt) { console.log("Tracking " + txt); } };
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script> <div data-bind="segmentTrack: true">CLICK ME</div>
与闭包:
(function(ko, analytics) { function sendTrack() { console.log("Tracking..."); analytics.track("stuff"); } ko.bindingHandlers.segmentTrack = { init: function(element) { console.log("Init"); ko.applyBindingsToNode(element, { click: sendTrack }); } } ko.applyBindings({}); })(window.ko, window.analytics); // window.analytics isn't quite okay yet! // Simulate loading analytics now: window.analytics = { track: function(txt) { console.log("Tracking " + txt); } };
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script> <div data-bind="segmentTrack: true">CLICK ME</div>
没错,在我的示例中,第二种情况引发了错误,而您在问题中提到没有任何反应 ,但是问题又没有包含实际的再现性,因此很难分辨出差异所在。
因此,analytics.js将自己的自身异步加载到页面中。 同时,它会将对象的缓冲版本将所有对API的调用排队。 analytics.js加载后,将执行队列中的所有调用。 然后重新定义其自身,将所有引用都破坏到原始window.analytics。 因此,对于我而言,足够快地遇到的所有调用都只能解决,这是使我的暴露函数成为一个函数调用,该函数调用返回window.analytics的当前版本。
(function (ko, $, analytics) {
function sendTrack(event, props) {
analytics().track(event, props);
}
ko.bindingHandlers.segmentTrack = {
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
var value = ko.unwrap(valueAccessor());
ko.applyBindingsToNode(element, { click: function () { sendTrack(value.event, value.options) }});
}
}
})(window.ko, window.jQuery, function () { return window.analytics; });
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.