Запустить обратный вызов после экземпляра объекта стиля класса в Javascript
Я беру чужой код и не уверен, что собираюсь делать что-то правильно.
Есть "класс" Tracker (в основном просто объект функций, включая "инициализатор").
Класс сделает звонок в стороннюю библиотеку.
Обратный вызов должен произойти после того, как результаты будут возвращены.
Вот что я пытаюсь сделать:
var tracker = Tracking.initialize({
prod: 'OurProduct',
requiredLayoutKeys: ["scr"],
requiredInteractiveKeys: ["name", "action"],
maxQueueSize: 5,
timeToSend: 5000,
});
// this code should happen in the callback once tracker is initialized:
InitSessionInfo(
{sid: tracker.__sid, product: tracker.prod},
function (returnObj) {
setSessionIP(tracker.getIP(),function(returnObj){
OurApp.auth(function (user) {
OurApp.initialize(user);
});
});
});
Вот как выглядит объект отслеживания в отдельном файле:
var Tracking = {
__required_layout_keys: null,
__required_interactive_keys: null,
__maxQueueSize: null,
__timeToSend: null,
__initialized: false,
initialize: function(config){
Tracking.__initialized = true;
Tracking.__required_interactive_keys = config.requiredInteractiveKeys;
Tracking.__required_layout_keys = config.requiredLayoutKeys;
Tracking.__maxQueueSize = config.maxQueueSize;
Tracking.__timeToSend = config.timeToSend;
Tracking.__bid = '';
Tracking.__sid = '';
Tracking.__ua = '';
// get user data from FingerPrintJs2.
// The callback needs to happen after these results are returned:
new Fingerprint2().get(function(result, components){
var ua = components.find(function(item){
return item.key === "user_agent";
});
Tracking.__bid = result;
Tracking.__sid = result + "." + Date.now();
Tracking.__ua = ua.value;
});
},
// there are other functions here that return ip, etc.
}
К сожалению, "трекер" всегда возвращается как неопределенный.
Обновить:
воткнув отладчик сюда:
var tracker = Tracking.initialize({
prod: 'OurProduct',
requiredLayoutKeys: ["scr"],
requiredInteractiveKeys: ["name", "action"],
maxQueueSize: 5,
timeToSend: 5000,
});
debugger;
значение tracker равно "undefined", а значение "Tracking" еще не имеет своего значения "sid".
Обновления в отслеживании:
var Tracking = {
...
initialize: function(){
...
return new Fingerprint2().get(function(result, components){
var ua = components.find(function(item){
return item.key === "user_agent";
});
Tracking.__bid = result;
Tracking.__sid = result + "." + Date.now();
Tracking.__ua = ua.value;
return Tracking;
});
}
1 ответ
Так, fingerprintjs2
это (глубоко внутри серии внутренних вызовов функций) возвращает setTimeout
, который по своей природе является асинхронным, но, к сожалению, вы не можете отключить по умолчанию. Вы можете увидеть, посмотрев на код внутри setTimeout
что он вызывает функцию, которую вы передаете get()
работать по истечении времени ожидания, так что вы можете использовать это с обещаниями, чтобы убедиться, что все происходит, когда они должны.
Что вам нужно сделать, это обернуть new Fingerprint2().get()
позвонить с обещанием, а затем решить это обещание внутриdone
"функция (та, которая вызывается внутри setTimeout), которую вы передаете в get
функция.
Затем вы можете вернуть обещание от initialize
функция в вашем Tracking
объект, чтобы вы могли от него зацепиться и выполнить действия после успешной инициализации / обновления данных.
Версия ES6 с использованием объекта Promise
var Tracking = {
__required_layout_keys: null,
__required_interactive_keys: null,
__maxQueueSize: null,
__timeToSend: null,
__initialized: false,
initialize: function(config){
Tracking.__initialized = true;
Tracking.__required_interactive_keys = config.requiredInteractiveKeys;
Tracking.__required_layout_keys = config.requiredLayoutKeys;
Tracking.__maxQueueSize = config.maxQueueSize;
Tracking.__timeToSend = config.timeToSend;
Tracking.__bid = '';
Tracking.__sid = '';
Tracking.__ua = '';
// get user data from FingerPrintJs2.
// The callback needs to happen after these results are returned:
// return the promise so we can chain
return new Promise(function (resolve, reject) {
new Fingerprint2().get(function(result, components){
var ua = components.find(function(item){
return item.key === "user_agent";
});
Tracking.__bid = result;
Tracking.__sid = result + "." + Date.now();
Tracking.__ua = ua.value;
resolve(Tracking); // resolve promise with updated Tracking obj
});
});
},
// there are other functions here that return ip, etc.
};
var tracker = null;
Tracking.initialize({
prod: 'OurProduct',
requiredLayoutKeys: ["scr"],
requiredInteractiveKeys: ["name", "action"],
maxQueueSize: 5,
timeToSend: 5000,
}).then(function (updatedTracker) {
tracker = updatedTracker;
console.log(tracker);
});
Совместимая с ES5 версия с использованием $.Deferred()
Документы с отложенным обещанием jQuery
Здесь немного меняется синтаксис, но ничего радикального - и идея точно такая же.
var Tracking = {
__required_layout_keys: null,
__required_interactive_keys: null,
__maxQueueSize: null,
__timeToSend: null,
__initialized: false,
initialize: function(config){
Tracking.__initialized = true;
Tracking.__required_interactive_keys = config.requiredInteractiveKeys;
Tracking.__required_layout_keys = config.requiredLayoutKeys;
Tracking.__maxQueueSize = config.maxQueueSize;
Tracking.__timeToSend = config.timeToSend;
Tracking.__bid = '';
Tracking.__sid = '';
Tracking.__ua = '';
// get user data from FingerPrintJs2.
// The callback needs to happen after these results are returned:
var deferred = $.Deferred(); // create deferred object
new Fingerprint2().get(function(result, components){
var ua = components.find(function(item){
return item.key === "user_agent";
});
Tracking.__bid = result;
Tracking.__sid = result + "." + Date.now();
Tracking.__ua = ua.value;
deferred.resolve(Tracking); // resolve deferred object with updated Tracking obj
});
return deferred.promise(); // return deferred promise that we can chain off of
},
// there are other functions here that return ip, etc.
};
var tracker = null;
// jQuery deferreds work with $.when(promise).then() syntax
$.when(Tracking.initialize({
prod: 'OurProduct',
requiredLayoutKeys: ["scr"],
requiredInteractiveKeys: ["name", "action"],
maxQueueSize: 5,
timeToSend: 5000,
})).then(function (updatedTracker) {
tracker = updatedTracker;
console.log(tracker);
});