Firebase receives update but doesn't trigger .on('child_changed') - javascript

When I first load the page, firebase works just fine. Any change to any of the data points triggers this function:
database.ref('users').on('child_changed, function...)
However, when I log out, and then log back in I can see the database being updated but the change is not triggering anymore until I reload the page. After reload, any change is reflected properly, but somehow logout/login stops the listening for change.
I wouldn't want users to have to reload every time they want to log out and then log back in.
Do I need another Firebase listener perhaps? I didn't find any other than these four:
child_removed, child_changed, child_added, value,
so any advice would be greatly appreciated.

I found the solution! Instead of having the database listeners inside angular .run() method, I refactored the code so listeners are inside of .factory(). Now every time user logs in/out the factory is consulted for any changes in the database.
That enables automatic update of the DOM elements every time something changes on the client and in the database.

Related

What is the proper way to handle a single user action that triggers two indexedDB write events to the same object store?

I'm working with a web page that has a tabbed display that simply hides all but the selected tab using the display style property. When a new tab is selected, a function is called that gathers some data from the page and writes it to an indexedDB object store to be used to restore the previous state of the tab, such as the selected element and cursor position, none of which seems efficient to save at every individual change.
At the same time, the important data is saved right away, such as a change event on a textarea, which will write data to the same object store as above.
My question is what should take place when the user writes new text to one of the textarea elements and, while the textarea still has the focus, clicks a button to navigate away from the tab (not the browser tab but just the tabbed display within the web page)? This single user action triggers two database write transactions at the "same" time and on the same object store.
In testing, I have tried to place a large amount of data in the textarea, before navigating away from that tab, in attempt at causing the change write event to take more time to complete; but, the write transaction triggered by the change event always completes before the event capturing the last state of the tab.
A reason for this may be that, apart from the last scroll position, all the data is taken from the dataset object of a small number of HTML elements, and that step may take longer before the transaction is even opened.
However, I'd like to feel more confident that this is coded as close to "fail proof" as possible, and would like to know how to prevent these two transactions from ever blocking or interfering in any way causing the loss of data or program failure.
I don't really know what to provide for a code example because there is nothing to show but a textarea element with a change event and a set of radio buttons, also with a change event, that invokes a function to gather data and open a write transaction before hiding one tab and showing the other.
Everything works and has not failed once yet, but how can I code it to be certain?
Thank you.
Addition After agonizing over this for awhile, I think I misunderstood the concept of blocking in indexedDB. I just assumed it had to do with two write transactions attempting to write to the same object store at the same time, but after reading further I don't think that is the case. If I understand correctly, this MDN document states that transactions are processed in the order they appear in the code, and the example is of two write transactions.
Thus, for my question of a change event triggering a write transaction at the "same" time as another write transaction is triggered, it would appear the only concern would be that one transaction overwrites the data written by the other transaction. The browser will handle the rest and I don't have to worry about transactions interfering or blocking, apart from their order when important. Blocking appears to be version change concern on an open database.
Regarding my original question, the change event always completed first in testing because its transaction was always opened first since it fires, I assume, on a blur event on the textarea which takes place before the change event on the radio buttons which fires on mouseup triggering the second write transaction. I assume that the second write transaction opened on the same object store won't begin until the first completes; but there isn't that level of description in the referenced document apart from below.
After the code is executed the object store should contain the value "2", since trans2 should run after trans1.
The point being that even if the first write transaction takes considerably longer relative to the second, the second will not start until after the first completes, and the only concern is the second transaction potentially overwriting data written in the first.
Sometimes I get myself confused and make issues where there aren't any and the coders of the browser have already taken care of it.
If I am still misunderstanding, I'd appreciate being corrected. Thank you.

How to get all form triggers (not just for the current script)?

I did the following:
Created a Google Form (e.g. form ID = ABC)
Created a Google Sheet (let's call it sheet1)
In sheet1's script editor, installed a trigger to my form with code such as the following:
var form = FormApp.openById("ABC");
ScriptApp.newTrigger("testFunctionSheet1").forForm(form).onFormSubmit().create();
When I call the following, I see my trigger was installed properly:
ScriptApp.getUserTriggers(form);
Everything is great. I can execute code whenever a Google Form is submitted.
Problem is, later on I go ahead and create a new Google Sheet (let's call it sheet2), which has similar code:
ScriptApp.newTrigger("testFunctionSheet2").forForm(form).onFormSubmit().create();
To be safe, though, I attempt to remove all the previous triggers from all my old scripts (i.e. sheet1). However, when I run:
ScriptApp.getUserTriggers(form);
... it returns one result (testFunctionSheet2) instead of returning both testFunctionSheet1 and testFunctionSheet2. Turns out it only returns triggers that are executed by the current script!
This is problematic because it may mean I accidentally have many scripts that are all executing upon a form's submission. If I never wrote down which scripts execute for which forms, I would have no idea what exactly is run from each submission. Some of those scripts may either do the same thing (which is a waste of CPU cycles at best, or will interfere with each other at worst), or they may do completely different things and potentially clash with each other.
I want a simple way to find all script triggers that will be executed on form submission. Something like if the function actually behaved as I would expect...
I.e. ScriptApp.getUserTriggers(form) should return something like:
sheet1: testFunctionSheet1
sheet2: testFunctionSheet2
This way I can easily tell which scripts will be executed upon form submission and can manually remove the old ones, to ensure nothing clashes.
Is there a way to find out which triggers will execute across all my scripts upon form submission?
Update: The documentation for getUserTriggers() clarifies that it will never return triggers for different scripts:
Gets all installable triggers owned by this user in the given form, for this script or add-on only. This method cannot be used to see the triggers attached to other scripts.
How, then, would I know all triggers associated with a given Google Form? Note: this doesn't necessarily have to be a programmatic solution. If there was a UI element in Forms that gave me this information, that would suffice too.
There doesn't seem to be a way to do this, but there are some workarounds that can make things a bit more organized:
Instead of installing the form trigger on a Sheet, install it on the Form. If you get into this habit, you can easily tell if there are scripts installed because the first place you'd check is in the Form's script. Simply run the get all triggers command as you tried above, and it'll work.
Instead of installing the form trigger on a Form, set the form to submit its responses to the Sheet, and use the onFormSubmit() method in SpreadsheetTriggerBuilder. To find out which trigger is associated with a form becomes as simple as opening the form, then going to its destination, and then looking if that script has a trigger for the form.
Hide the trigger script names in some property on the Form that you don't plan on showing to the user (e.g. customClosedFormMessage). Set it to something like This script has an active trigger associated with sheet1. You can create a helper function that before installing a trigger, it ensures that that text doesn't exist there (if you want to limit to 1 trigger per form, for example).
Go to https://script.google.com/home/triggers?trigger_type=3&document_id=ABC
That should give a list of all triggers from form with id ABC. You can clear filters there and add new filters.
As the OP already mentioned on the question, the documentation says that a script can't get triggers created by other scripts.
If you are the only one that create triggers from your script projects, then go to https://script.google.com > Triggers, there you will find a list of all the triggers created by your account.
I didn't tried it yet, but I think that one alternative is to enable the Google Apps Script API on the projects that create triggers and add a function to be called through Google Apps Script API to "log somewhere" the triggers created by that project.
Regarding to "log somewhere" maybe the easier setting is to email the log to the "active user".

Javascript events using H.datalens.Provider

Are there any events to subscribe to using
H.datalens.Provider
? So one can know when all data has been loaded for example, or if there was an error.
I'm afraid not. There is an "update" event being triggered when the data gets updated (see https://developer.here.com/documentation/geovisualization/datalens/h-datalens-provider.html) but I do recall it triggering multiple times. Afaik there's no easy way to know the data has finished loading.
A trick I've seen using is listening to the event and starting a timeout, resetting it every time a new update event gets triggered. When the timeout is finally able to execute, the updates are over. This is not by any means a good solution, but might be of help.

React - When refreshing getting always to initial page

I'm working on a project using react with flux architecture.
I have several views and a store called ContextStore in which I save the current view in the state, so that when an action to change the view is triggered this store change his state and the Main view listen and change it.
But the problem is that always when I refresh the page with F5 it always goes to the initial Views.
What is more, if I press the back button the View has no change.
I think that my problem is because when I refresh the Main view loads again the initial state. How could I solve it?
Thanks!
You might want to look into using a router to manage your views. Here's the one I use: https://github.com/rackt/react-router. When you transition to different views (routes) it adds to the history stack so you can use the back button. However, I don't have the use case where you need to stay on the current view when you refresh, so you might need to use cookies or session storage in those instances in any case.
You are right, when hitting F5 you are completely reseting all javascript, ergo the store looses its state. You need to use some kind of storage for saving the state. Classical ways are cookies, or you could use IndexedDB which is included into HTML5

How to handle reload & close button differently?

I want to put some logic before user leaves a page, but I want to handle reload button & close button action differently.
All I know is that there is onbeforeunload event that will be called before user unload the page, but it doesn't solve my use case.
I want to create some statistic/tracker, something like this:
$(window).beforeunload(function() {
if (user click browser's close button)
// track_user_click_close_button()
else if (user click browser's reload button)
// track_user_click_reload_button()
});
You can't know the URL user will be navigating to. This is not a jquery/js issue.
The bottomline is - you cannot do what you want.
Update
But if you try sometimes, you might find - you get what you need.
As stated in this SO answer to a similar question, there is something you can do to overcome this inability. I strongly suggest you to read the described approach.
If it's not suiting your needs, please open a new SO question with detailed explanation of what you're trying to do, and we'll try to help you.
Another update
Unfortunately, there's no way of determining this out-of-the-box. You can try the following approach:
$(window).beforeunload(function() {
// should be a synchronous AJAX-call, as async one won't work
persistLeaveOnServer();
});
$.ready(function() {
tellServerWeAreBack();
});
And on server side you should maintain the session state according to that. Once certain amount of time has passed (probably, several seconds), you consider the session ended and persist the statistics as UserClickClose. If tellServerWeAreBack request is received before this time passed, you save UserClickRefresh stat value.
beforeunload fires whenever the user leaves the page. If you want to differentiante between a refresh and a close you must be able to detect the page reload.
You could keep an information telling the page that it is unloading at xx:xx time. Log the fact to some place. When the page is loaded, check whether there is some logged evidence that the page was quit recently (depending on your definition of recently) and turn the event into a refresh event: (see here for an example)
This may not be able to differentiate between a refresh and a user closing then reopening the page quickly (under your time treshold).
Note: the linked page mentions using hidden form elements that are persisted between refresh, but says that browser support is all over the place; I'm wondering if this is still the case or not. Storing information in the window object will survive refreshes so you may want to explore this avenue

Categories