2016-04-07 7 views
2

Ich benutze Knockout, um eine benutzerdefinierte Bindung für analytics.track zu erstellen, aber es scheint Probleme zu haben. Es scheint, wenn der analytics.track in mehr als zwei Funktionen verschachtelt ist, schlägt der Track-Aufruf stillschweigend fehl. Es trifft den Rückruf nicht und es meldet nicht in Segment-Debugger. Ich habe 2 Beispiele zur Verfügung gestellt, das Problem demonstriert hier:Wie man analytics.js von segment.io in einer Knockout-benutzerdefinierten Bindung verwendet

ohne Verschluss (Werke):

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({}); 

Mit Verschluss (nicht funktioniert):

(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: Beachten Sie auch, das funktioniert mit wenn ich die analytics.track init bewegen:

(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); 

Bitte geben

+0

Ihre letzte Änderung hat meine Antwort ungültig gemacht (ich bin mir nicht sicher, ob ich sie löschen oder sie dort für andere belassen soll, die darin Verwendung finden könnten). Mit deinem letzten Beitrag denke ich, dass es unmöglich ist, zu erzählen, was vor sich geht. Du solltest ein [mcve] erstellen und die Frage damit aktualisieren, weil ich derzeit vermute, dass das Problem in etwas liegt (load order, code, etc), das nicht im Post angezeigt wird. – Jeroen

Antwort

0

So lädt analytics.js asynchron seine selbst in der Seite. In der Zwischenzeit werden alle Aufrufe der API mit einer Snub-Version des Objekts in die Warteschlange gestellt. Sobald analytics.js geladen wird, führt es alle Anrufe in der Warteschlange aus. Dann definiert es sich selbst neu und bricht alle Refs zum ursprünglichen window.analytics. Daher müssen alle Aufrufe, die schnell genug für My gefunden werden, nur dafür sorgen, dass mein Exposor zu einem Funktionsaufruf wird, der die aktuelle Version von window.analytics zurückgibt.

0

Dies ist sehr wahrscheinlich, weil die Dinge auf dem Objekt window initialisiert werden. Da das Programm sofort ausführt, wird die analytics Variable auf window.analyticseingestellt, sobald der Browser auf den Fehler trifft. Im ersten Fall wird window.analytics aufgelöst, wenn der Code ausgeführt wird.

anders ausgedrückt: der Verschluss fängt window.analytics in eineranalytics Variable zum Zeitpunkt der IIFE führt scoped.

Hier ist eine Demo, die das Problem zeigt.

Ohne Verschluss:

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>

vs mit Verschluss:

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

Es stimmt, in meinen Beispielen das zweite Szenario wirft einen Fehler, während Sie in der Frage nichts erwähnt passiert, aber dann wieder die Frage enthält keine tatsächliche Repro, so ist es schwer zu sagen, wo dieser Unterschied liegt.

+0

Ich habe meine Frage aktualisiert. Ich verstehe nicht, warum ein Ladeauftrag den Code so beeinflusst? –

Verwandte Themen