Angulartics tracking event missing - google-analytics

I'm using angulartics with google analytics and intercom.
In my current case i have to track the same event multiple times in a loop,but angulartics seems to throw the events away if they occure to fast successively.
When using the debugger, each event is tracked, also if i call the eventTrack with some delay for each event.
But without debugger and delay the event is only tracked once.
Am i missing anything or is this exactly what is recommended, delaying the track-call?
Code-Example:
// looping a list of things you want to track for each element
for (var i = 0; i < length; i++){
// call the event tracks in parallel,
// fired async with a delay of 1000 ms between each
setTimeout(function delayed() {
$analytics.eventTrack(action, trackingEvent);
}, 1000 * i);
}

Related

Is it possible to destroy firestore listeners soon if client is not connected? [duplicate]

Is there any way to pause firestore listener without removing it?
I have multiple firebase listeners, some are dependent on other, that changes or start other listeners on data change. Lets say my first listener starts a second listener its onSnapshot. First listener started on useEffect. For certain condition I may not want to change the second listener, so I need to discard data change update from first listener.
If condition met (button click), I discard data changes on first listener for a few moments. Currently I'm doing this using a boolean with useRef. My react app is working fine, with dependant listeners like this. I could remove the listener but I do not want to remove and recreate the listener.
I was wondering if there is a pausing mechanism or method available for any listener. I think it will save a tiny read cost if there was such a method because I'm not using that data sent onSnapshot.
Code example:
useEffect(() => {
let firstListener, secondListener;
//console.log("useEffect...");
function ListenerFunc(p) {
secondListener = await firestore
.collection("test")
.doc(p)
.onSnapshot((doc) => {
//console.log("Current data: ", doc.data());
//Need to discard unwanted change here.
//Changing it on button click for a 2 seconds then it changes back to : pauser.current = false.
if (pauser.current) {
console.log("paused for a moment.");
//pauser.current = false;
return;
}
else {
//update.
}
})
}
firstListener = firestore
.collection("test")
.doc("tab")
.onSnapshot((doc) => {
//console.log("Current data: ", doc.data());
var p = doc.data().p; //get variable p
ListenerFunc(p);
});
// cleanup.
}
Unfortunately this is not possible. If you need to stop listening for changes, even temporarily, you have to detach your listener and attach a new one when you want to start listening again, there is no pause mechanism for listeners.
You could open a Feature Request in Google's Issue Tracker if you'd like so that the product team can consider this, but given that this has already been proposed in this GitHub Feature Request for the IOS SDK and it was rejected I don't see this changing anytime soon.

Why for loop is not working in ionic ionViewWillEnter method

I am calling a method "allComments()" in ionViewWillEnter() method, but it is not not binding name and profile every time I am entering in view. Not able to find any valid reason. There's no error in the code
allComments() {
this.comments=[];
let arr=[];
this.com=[];
console.log(this.challengeId)
this.https.get('https://dareost.firebaseio.com/comments/'
+this.challengeId+'.json').map(res=>res.json()).subscribe(x=>{
this.com=x
for(let key in this.com) {
this.comments.push(this.com[key])
}
this.length = this.comments.length;
for(let i=0;i<this.comments.length;i++){
let a=this.comments[i]
console.log(a)
for(let key in a){
arr.push(a[key])
this.arr.push(a[key])
}
}
for(let i=0;i<this.arr.length;i++){
for(let j=0;j<this.users.length;j++){
console.log(this.arr[i].commentedBy)
if(this.arr[i].commentedBy == this.users[j].uid){
console.log(this.users[j].name1)
this.arr[i].name=this.users[j].name1
console.log(this.arr[i])
this.arr[i].profile=this.users[j].profileUrl
}
}
}
It is sometimes not printing this.arr[i].name on console and sometime it gets print.
ionViewWillEnter() gets for a less time and heavy loops and heavy processes cannot get process during this time. It totally depends on the device's RAM. A device having good processing speed will not load heavy data while the device with slow processing speed can process heavy data.

GTM Timer Triggers

Following situation:
On a single page application, an event : ArticleClick is fired when we open a specific article on that page. I consider an article read when 10 seconds have passed after the ArticleClick event.
So far so good, this can be accomplished using the Timer functionality in GTM.
Only problem is that, when the event has fired and after 9 seconds i open another event, this will cause a second timer to start and no matter what i do as long as the website is open (because it's single page) there will always be a read event. Is there a simple way to stop the first timer when another article (and another timer) is opened before the 10 secs has reached?
Solved by using a datalayer variable to store the state of the timer (running or not).
Mind that the true or falses here are strings instead of booleans, this because the default value in GTM for the DL-variable needs to be set to false to make this work,doing that in the GTM-interface automatically makes the value a string.
<script>
(function() {
var timerNumber = 1;
var limit = 1;
// timer
var fireTimer = function() {
window.dataLayer.push({
'event' : 'ArticleRead',
'custom.timer.running' : 'false'
});
timerNumber += 1;
if (limit < timerNumber) {
window.clearInterval(timerId);
}
};
if ({{custom.timer.running}} == 'false') {
window.dataLayer.push({ 'custom.timer.running' : 'true'});
var timerId = window.setInterval(fireTimer, 10000); }
})();
</script>
So now when we trigger the timer a second time and the timer hasn't reached it's 10000 milsecs it does not continue and it starts again.

Invoke value event handler only on value change in Firebase

Is there a way to invoke the value event handler only on value change in Firebase? If I just add the value event handler without any special code, it will be called once on reading the initial value and then on any value change. I want to avoid invoking the event handler on reading the initial value.
One of the use cases where I need this functionality is that I am working on an app where user can add tasks for some other users. The other users can either accept or reject a task. There is a server which is monitoring these tasks on Firebase and it sends a push notification to the creator of the task whenever a user accepts or rejects a task i.e. whenever there is a change in the status of task.
I have tried two solutions.
Solution 1:
Have a map and add an entry to the map when the value event handler is called if it is not already present and if the the entry is present, then do the work required on value change. This solution works but I need this in several different cases and I have to create this map in all such cases and I didn't find it to be a convenient solution.
Solution 2:
Add the value event handler like this
ref.on('value', (snapshot) => {
console.log('Initial call ', this.initialCall);
if(!this.initialCall) {
// Do work
} else {
this.initialCall = false;
}
}, {initialCall: true}) // {initialCall: true} is the context which is provided as this in the event handler
Here my thinking was that I can check if the event handler is called for the initial value by checking if this.initialCall is set to true. If it is, then set the this.initialCall to false and then in the subsequent invocations, this.initialCall should be false and I can do the work required for a value change. Using this solution what I observed was that the this.initialCall was undefined the first time the handler is called and then it was set to true and then it was true for all value change event handler invocations for all the tasks, not just the one for which it was set to true.
With regards to solution 2, I am not a JS expert and it is possible that due to some gap in my JS knowledge, I am doing something wrong due to which it doesn't work as I expected.
Please let me know if you have an idea/solution which can be used to call the value event handler only on value change.
A value event in Firebase is invoked immediately with the current value and then whenever the value changes. If you only care abut when the value changes, you can simply ignore the initial event:
var isInitialValue = true;
ref.on('value', function(snapshot) {
if (isInitialValue) {
isInitialValue = false;
}
else {
// TODO: handle subsequent changes
}
});

Meteor How to block a method call before the first one is finished?

I have the following scenario:
Client side has a button clicking it will execute Meteor.call method on the server-side which will call API and fetch products, During this time I wan't to disable this button + block this method from executing again basically nothing stops you from clicking the button 100x times and server will keep on executing same method again and again.
Few ideas I had in my mind: Use sessions to disable button (Problem: can still using the console Meteor.call and abuse it)
I also looked at Meteor.apply in the docs with wait:true didn't seems to stop from method execution. I honestly not sure how this kind of thing is handled with no hacks.
Client-side:
'click .button-products': function(e){
Meteor.call('getActiveProducts', function(error, results){
if (error)
return Alerts.add(error.reason, 'danger', {autoHide: 5000});
if (results.success)
return Alerts.add('Finished Importing Products Successfully', 'success', {autoHide: 5000});
})
}
Server-side
Meteor.methods({
getActiveProducts: function(){
var user = Meteor.user();
var api = api.forUser(user);
importProducts = function(items){
nextPage = items.pagination.next_page;
items.results.forEach(function(product){
var sameproduct = apiProducts.findOne({listing_id: product.listing_id});
if (sameproduct) {
return;
}
var productExtend = _.extend(product, {userId: Meteor.userId()});
apiProducts.insert(productExtend);
});
};
var products = api.ProductsActive('GET', {includes: 'Images', limit: 1});
importProducts(products);
while (nextPage !== null) {
products = api.ProductsActive('GET', {includes: 'Images', page: nextPage, limit: 1});
importProducts(products);
}
return {success: true};
}
});
From the Meteor docs:
On the server, methods from a given client run one at a time. The N+1th invocation from a client won't start until the Nth invocation returns. However, you can change this by calling this.unblock. This will allow the N+1th invocation to start running in a new fiber.
What this means is that subsequent calls to the method won't actually know that they were made while the first call was still running, because the first call will have already finished running. But you could do something like this:
Meteor.methods({
getActiveProducts: function() {
var currentUser = Meteor.users.findOne(this.userId);
if (currentUser && !currentUser.gettingProducts) {
Meteor.users.update(this.userId, {$set: {gettingProducts: true}});
// let the other calls run, but now they won't get past the if block
this.unblock();
// do your actual method stuff here
Meteor.users.update(this.userId, {$set: {gettingProducts: false}});
}
}
});
Now subsequent calls may run while the first is still running, but they won't run anything inside the if block. Theoretically, if the user sends enough calls, the first call could finish before all of the others have started. But this should at least significantly limit the number of etsy calls that can be initiated by a user. You could adapt this technique to be more robust, such as storing the last time a successful call was initiated and making sure X seconds have passed, or storing the number of times the method has been called in the last hour and limiting that number, etc.
A package I wrote a while back might come in handy for you. Essentially it exposes the Session api on the server side (hence the name), meaning you can do something like ServerSession.set('doingSomethingImportant', true) within the call, and then check this session's value in subsequent calls. The session can only be set on the server, and expires upon connection close (so they could spam calls, but only as fast as they can refresh the page).
In the event of error, you can just reset the session. There shouldn't be any issues related to unexpected errors either because the session will just expire upon connection close. Let me know what you think :)

Resources