I have a simple Electron application that queries a SQL database and displays the output via an HTML table. I have everything working correctly, but now I need to "refresh" the HTML table every X minutes (with the new results of the SQL query).
Right now, I have it working correctly using the meta tag directly in the HTML with: http-equiv="refresh" content="300". This correctly refreshes the page every 5 minutes, which is exactly what I want.
Although, the problem is that the refresh causes the screen to go white while the SQL query executes and the HTML is built. Obviously, the better solution would be to use the DOM and only modify the cells that have actually changed, since the last refresh. The problem I am running into, is getting "setInterval" to work correctly.... Once again, this is a VERY SIMPLE electron application. I am using their starting boiler plate. I have tried adding the "setInterval" in the <body> tag, using code like this:
<body onload='setInterval(updateTable(), 300000);'>
but the code only fires once... I have also tried adding the following code at the end of the body (just inside the </body> tag):
<script>
window.onload=function(e){
setInterval(updateTable(), 300000);
}
</script>
...removing it from the window.onload handler...:
<script>
setInterval(updateTable(), 300000);
</script>
...and also by moving it to the "renderer.js" file:
setInterval(updateTable(), 300000);
in all cases, it only fires once...I know this because the first line of code in updateTable() outputs the current date and time to the console, via console.log()..
I have tried lowering the timeout value to 10 seconds (from 300000 to 10000), just so I don't have to wait so long while testing and that didn't make any difference. I suspect the problem I am having has something to do with my lack of knowledge of the electron framework (like, perhaps the different "processes") and I have been searching for solutions for two days now, with no luck. Any advice on how I can accomplish this, is MUCH APPRECIATED!
TL;DR
Your issue has nothing to do with Electron and more with what exactly you pass to setInterval. You're not passing the function updateTable, but the result of the function call updateTable(). Remove the parentheses after the function name.
Analysis
Both functions setInterval and setTimeout expect a function as their first parameter, which they will call at a specific time or regularly. What you pass to setInterval is, however, not a function. You write:
setInterval(updateTable(), 10000)
When this line is executed, updateTable is called and its return value is passed to setInterval. (If the function doesn't explicitly return anything, it returns undefined.) That's why your function is just called a single time (when setting up the timer).
If you write
setInterval(updateTable, 10000) // no parentheses
you're actually passing the function to setInterval, which will then run it repeatedly.
You may wonder why your workaround using setTimeout works. This is because you actually pass a function to it. You're specifying the function inline, but don't call it at that time. It does not matter that inside that function, you make the call to updateTable. What matters is what you pass to the timer functions.
I have found a fix/workaround... either there is a "bug" with setInterval or (most likely) I am just missing something due to my "newness" to the frakework. But, instead of using setInterval, I switched to setTimeout, then in the callback, after calling updateTable(), I just set another setTimeout. For whatever reason, this works perfectly.... basically, in "renderer.js", I replaced:
setInterval(updateTable(), 10000);
with
let timer = setTimeout(function refreshTimer() {
updateTable();
timer = setTimeout(refreshTimer, 10000);
}, 10000);
Even though these are functionally equivalent, for some reason it now works perfectly.
Related
I'm using ui-grid 3.2.1.
Trying for a long time now to find an event that notifies me when rows are rendered in the DOM.
I looked a lot in SO, and in their issues in Github.
My test to see if rows are rendered is basically $('.ui-grid-row').length > 0.
I tried rowsRendered event, modifyRows(data), all sorts of $timeout(0) in almost every spot I could, nothing worked, all callbacks are called when the above jQuery still doesn't have results.
As a last resort I found a very inefficient solution - I $watch the .html() changes of .ui-grid-contents-wrapper, which contains the .ui-grid-row elements, and when I find one, I turn off the watcher and call the callback. It's bad but it works.
Note - The rows/columns somtimes contain inner directives which may take some time to render. I don't think it should influence rowsRendered() event.
Please, can anybody help with this?
No support from ui-grid team sadly.
EDIT:
plunkr that show there are no .ui-grid-row in DOM when rowsRendered() is called:
https://plnkr.co/edit/8clwC5hkwhAEjvoLZ6vO?p=preview
Try
var rows= gridApi.core.getAllVisibleRows(gridApi.grid);
inside rowsRendered function.
I am getting an "Element is no longer attached to the DOM" error from Geb tests. The thing that's confusing me is that the error is from within waitFor itself -- I inserted the wait specifically to allow the async activity on the page to complete before moving ahead with clicking a link, which was previously the source of the same error. If the wait itself fails, now I'm at a loss.
The code is something like
waitFor { $("div", text: "... search string ... ") }
$("a", id: "element-id").click()
and the stack trace shows that the waitFor itself is actually the problem:
at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:187)
at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:145)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:554)
at org.openqa.selenium.remote.RemoteWebElement.execute(RemoteWebElement.java:268)
at org.openqa.selenium.remote.RemoteWebElement.getText(RemoteWebElement.java:152)
at geb.navigator.NonEmptyNavigator.matches_closure28(NonEmptyNavigator.groovy:474)
at geb.navigator.NonEmptyNavigator.matches(NonEmptyNavigator.groovy:471)
at geb.navigator.NonEmptyNavigator.filter_closure2(NonEmptyNavigator.groovy:63)
at geb.navigator.NonEmptyNavigator.filter(NonEmptyNavigator.groovy:63)
at geb.navigator.NonEmptyNavigator.find(NonEmptyNavigator.groovy:48)
at geb.content.NavigableSupport.$(NavigableSupport.groovy:96)
at geb.Browser.methodMissing(Browser.groovy:193)
at geb.spock.GebSpec.methodMissing(GebSpec.groovy:51)
at [my test]_closure7([my test].groovy:147)
at [my test]_closure7([my test].groovy)
at geb.waiting.Wait.waitFor(Wait.groovy:106)
From the stacktrace I can see that you use that selector inside of a test class and not a module so the possibility of a module base element being detached can be ruled out.
If this is happening consistently for you then it means that one of the elements selected by the div selector gets removed from DOM before its text is being retrieved to filter on it.
There are two reasons why this can happen:
Your selector is very slow - selecting all div elements in a page and then filtering them based on text in the JVM can take a lot of time. Assuming that you use the default waiting preset then if that selector takes more than 5 seconds then the waitFor {} block will simply run once, get the exception and never retry because it runs out of time. You should do as much filtering as possible in the browser, that is use a CSS3 compatible selector and use Geb's text filtering extension on an as small as possible element set.
Your page is async in a periodic way and it changes quicker than the selector is able to filter based on element text. This would be again possible because your selector looks like it could be potentially very slow.
Basically I would suggest coming up with a more specific selector than what you have there currently.
I'm looking for an event fired by polymer-layout when it's finished laying out, similar to the polymer-grid-layout event. Doesn't seem to be one. Am I missing something?
After my attempts at polymer-grid-layout (Autosizing canvas inside a polymer grid layout) I've decided to convert everything to nested polymer-layouts instead. After a few hiccups (e.g. the dart version of polymer-layout doesn't work if you put polymer-layout as an element directly under template, whereas the js version does - don't know which is wrong) the approach seems to be working.
The one exception is that I was previously relying on polymer-grid-layout to tell me when the canvas had been resized properly. But with polymer-layout I have the same timing problem but without the same solution it appears.
Any way around this?
thanks
Anders
Dart polymer_element/polymer_ui_element are a bit outdated. I'll take a look at what changes were be made in JS polymer-layout since I last revisited Dart polymer-layout (probably Mo/Di).
Can you please create an issue in https://github.com/ErikGrimes/polymer_elements so you get notified when the update is made.
You are right that polymer-layout is missing a layout event. I filed an issue here https://github.com/Polymer/polymer-layout/issues/3
In the meantime, you should be able to capture the timeline in attached.
attached: function() {
this.async(function() {
this.async(this.layoutHappened);
});
},
layoutHappened: function() {
}
I used nested async because I don't want to worry about whose attached is called first (this one, or the one in the polymer-layout). And yes, this is exactly the kind of fiddly construction that is avoided by having an event.
Per the remoteFunction documentation one can cause a javascript function to be called when the remoteFunction finishes, using the onComplete parameter. From examples I've seen on the web, one can supply a function with an event parameter, i.e.
onComplete: 'finishUp(e)'
Then I found this is broken in 1.3.6, per Grails bugs filed, here and here, which was supposed to be fixed for 1.3.7 (perhaps 1.3.6), per the bug resolutions.
However, this is still broken in my 1.3.7. Are you able to get this to work? Is there a bug in my syntax. Note if I drop the 'e', I get the function to be called (can tell by an alert). But, if I add in the "e", the function doesn't get called.
Thanks
Try this:
onComplete: 'finishUp'
And see if it calls the function and if the event object is present in
function finishUp(e) { ... }
I am not really sure what to do in this situation. I have some jquery ui 1.7 tabs that are ajax enabled. Now when a tab is clicked it goes to my asp.net mvc controller action method. That then does whatever is needed and return a partial view.
Now I don't know why but sometimes my server hangs but then again I am guessing all servers hang since sometimes when I go to sites it take forever to load but if you do a refresh it loads up instantly and that's the same case with my site.
My site will load up a tab super fast for X number of times then all of a sudden a request will just hang and maybe like 15seconds later it will load up. Or if you just refresh the page it will go back and start loading them up super fast again.
The problem though is the request is sent to the server where it hangs. So I tried to setup a jquery timeout on all my ajax stuff and that calls an abort to the jquery ui tabs.
But it never works and I guess from what I gathered reading on this site is because the request is on the server and abort won't stop stuff on the server. So if I look at firebug that request that hanged is stil running.
Now this causes a huge problem for me since it screws up the entire page what is heavily ajax. Like if the user tries to click on say another tab they will most likely have to click 2 times to get it to load up. Another thing what happens is if that request ever finish hanging whatever tab they are on will merge with that tab. So sometimes one tab will have parts from all the other tabs.
So if it hangs and does not finish it really messes with the ajax tabs. I have no clue how to fix this.
So I am not sure what to do.
Let them hang for however long it takes the server to figure out how to finish that request(when a ajax request is made I disable all tabs. This is because if a person say loaded up a tab and did not let it finish and tried to go to another tab the same problem would occur with the tabs merging together). Or abort the request and have a screwed up tabs.
Great choices I got. Anyone got any better choices?
Thanks
We have a similar situation here in that the 1st person to hit the site for the day will incure a 15 second delay while things are loaded.
In our situation, on all calls to the server via jQuery, I have set a normal javascript timeout for 2 seconds. After 2 seconds I pop up a small div saying something like things are talking longer than expected and please be patient.
after a further 6 seconds i close that div and open a new one with more of an apology.
not a great solution but it does keep the user in the loop, comfortable that things are ticking along and that we acknowledge things are not perfect.
warm and fuzzies as we call them here. :)
I'm not sure what you mean by "jquery timeout". if you mean setTimeout, that definately won't work. If you mean, on the other hand,
$.ajax({
url:"myserverprocess",
timeout: 200,
error: function () { /* try again */ },
success: function (myadata) { alert("mydata")}
});
then that should work. Try the timeout option if you haven't yet.
edit:
you could try :
$(selector).tabs({
ajaxOptions: {
url:"myserverprocess",
timeout: 200,
error: function () { /* try again */ },
success: function (myadata) { alert("mydata")}
}
});
We've had good success using jquery queue manager - http://www.protofunc.com/scripts/jquery/ajaxManager/
When a second request is performed it aborts the first request. I'm not sure about a timeout, but there are several options you can play with.
You could use Jquery to set a timeout on your ajax call and then catch it in the error section. Once caught, you could deal with retrying or doing any needed cleanup.