vue load synchonous initialization - javascript

I have a program written in vue and electron.
This program calls an init function that takes around 15 seconds to complete.
The issue I am having is that I can't seem to make this run in a background thread or after the component has rendered a loading view. The application is just a white blank screen while the init function is running.
I would assume that it would be easiest to just load a loading view and let it be frozen during startup, so how would I actually go about doing that?
I tested with something like this:
updated() {
console.log("running init");
init();
this.loading = false;
console.log("completed init");
}
but it appears as if it isn't always called.
To force it I updated some data in the mounted hook, but then it freezes on the white screen

Related

How can I re-load images in p5.js once they've changed since runtime?

I have a python file outputting a .png file to a local directory once a second, and this p5.js Javascript file is being hosted from this directory on a server. My issue is in trying to use the loadImage() function to load this local .png -- if I do so, it'll only refer to the initial value of it, and not its new changed value. Even when using a callback function inside draw(), it is very buggy, and does not change. Here's the file:
let splot;
//...
//irrelevant classes
//...
function draw() {
background(245);
solOnePane.display();
s1plot = loadImage("plot.png", imageLoaded);
}
function imageLoaded()
{
console.log("Debug");
image(s1plot,200,200);
}
The result is a super buggy and unchanging image file that only reflects the image file at the state of loading the site. Upon a refresh, the file is updated. So, how can I write code with loadImage() to load an image at the current moment?
Thanks so much.
If the image is saved at a set internal externally, let's say every second, you could use setInterval() every 1100ms for example to reload the image:
var s1plot;
function setup(){
//...init your things here
//reload the image every 1.1s
setInterval(loadImage, 1100, "plot.png", imageLoaded, imageLoadFailed);
}
function imageLoaded(loadedImage)
{
s1plot = loadedImage;
console.log("image loaded", s1plot);
}
function imageLoadFailed(event){
console.warn("image load failed", event);
}
function draw() {
background(245);
if(s1plot){// try to display the image only when it's available
image(s1plot, 200, 200);
}
}
You could use draw() as well and change the frameRate() to so a new frame is rendered every second or so. Here's a modified version of the above using frameRate():
var s1plot;
function setup(){
//...init your things here
//set frameRate to 1 frame every 1.1s
frameRate(1000 / 1100);
}
function imageLoaded(loadedImage)
{
s1plot = loadedImage;
console.log("image loaded", s1plot);
}
function imageLoadFailed(event){
console.warn("image load failed", event);
}
function draw() {
background(245);
if(s1plot){// try to display the image only when it's available
image(s1plot, 200, 200);
}
// reload the image
loadImage("plot.png", imageLoaded, imageLoadFailed);
}
This may be simpler (sometimes setInterval's scope can get hairy), but it also means you're limited to slow render updates. You may want this if the p5 sketch if simply displaying an image, but not if for example you want to handle reactive user interaction as well.
The code above isn't tested, but hopefully illustrates the idea.
It's worth double checking loadImage() reference when in doubt.
For example, these details are important:
The image may not be immediately available for rendering. If you want to ensure that the image is ready before doing anything with it, place the loadImage() call in preload(). You may also supply a callback function to handle the image when it's ready.
In your case the second option (supplying a callback function) applies, however you've forgotten to add the image argument to the image load callback.
This assumes there are no issues writing plot.png to disk with no errors and the timing is a bit of a hack.
In an ideal world you would have the first system which writes plot.png send a message to p5 when the image has been successuflly been written and is ready to be loaded. (If plot.png is for example generated by a python script using matplotlib or something similar you could use a server sent event or websocket library to which p5 can connect to and listen for the message to load the image)

Not able to clear my setInterval in Ionic

I have an IONIC 4 application where I need to call an api every 20 seconds and if the user moves to other page need to stop calling that api. I am able to make the api call at every 20 seconds but not able to stop it when I move to some other page. Here is my code below, may I know where I went wrong?
rateTimer:any;
constructor(private loginServiceService: LoginServiceService) {
this.loginServiceService.getappData();
this.rateTimer=setInterval(() => {
this.loginServiceService.getappData();
}, 10000);
}
// When I move to other page, I clear the setInterval from here
ngOnDestroy() {
clearInterval(this.rateTimer);
}
As far as I know Ionic has a cache for page-navigation which is why ngOnDestroy/ngOnInit will not always work. However, there's ionViewDidLeave which should definitely fire, once the current page is moved away from (see https://ionicframework.com/docs/api/router-outlet#life-cycle-hooks for more details):
export class YourComponent {
ionViewDidLeave() {
// Do actions here
}
}

How to run a task after the page being killed in browser?

First of all, it has two pages: example.com/pageA and example.com/pageB, it's not a SPA.
How to run a delay task after the page being killed by history.back?
I tried using setTimeout but failed to execute the task after history.back, because the timer will be clear in stack when page change.
var a = 1
function refresh() {
// <p id="count"></p>
count.innerText = a
}
function foo() {
a += 1
refresh()
}
// called in PageB
function goBackA() {
setTimeout(foo, 1000)
history.back()
}
In PageA the count still be 1 instead of 2.
For security reason, your goal to run some code after page being killed will never be supported by the browser, because it's dangerous when some code can run on a different page.
Once the page being reload/killed, all the unfinished tasks will be clear even if in a SharedWorker.
So, two ways to accomplish your logic:
change to SPA
give another page a hint like query

Adding a CSS class is not rendered by the browser

I have the following code (Backbone view, rendering using Handlebars):
_this.$el.addClass("loading");
_this.el.innerHTML = _this.template({
some: data
});
_this.otherCPUConsumingRenderingFunctions();
_this.$el.removeClass("loading");
The CSS class displays a "Loading" message on screen to warn the user, since rendering takes time due to a large amount of data and a complex rendering.
My problem is that the CSS class is correctly applied (I see it in the inspector) but nothing is displayed on screen.
If I put breakpoints and go step-by-step, it will work perfectly.
The issue occurs both with Chrome and Firefox.
No rendering function in browsers is synchronous. So your otherCPUConsumingRenderingFunctions is most probably returning as soon as you call it. It does it's thing later asynchronously.
That is why your loading class gets removed as soon as it is added.
Most likely you'll need to use a callback after the rendering function completes. Also remember expensive rendering operations, depending upon their design, can be blocking — meaning the dom does not get a chance to re-render until all the work is done. In this case it will add the loading class and remove it all before the dom redraws. Stepping through your code provides the browser time to re-render which is why you'll see it working when debugging.
Perhaps something like this
_this.otherCPUConsumingRenderingFunctions = function (callback) {
// do work here
callback();
};
_this.$el.addClass("loading");
_this.el.innerHTML = _this.template({
some: data
});
// You can use a timeout to "schedule" this work on the next tick.
// This will allow your dom to get updated before the expensive work begins.
window.setTimeout(function () {
_this.otherCPUConsumingRenderingFunctions(function () {
// Ensure this only runs after the rendering completes.
_this.$el.removeClass("loading");
});
}, 1);
The backburner.js project was created to help mitigate this kind of problem. It works well with Backbone too.

Javascript - Show Spinner, Save Data Synchronously, Remove Spinner

I am trying to create a javascript plugin that allows you to hook into the save operation. I want some logic wrapped around the logic though:
Show a spinner
Execute save hook-in
Execute save logic
Remove Spinner
here is an example of my code:
function save(){
var settings = getSettings();
showSpinner();
// Hook-in call
if(settings.onSave)
settings.onSave();
saveState();
removeSpinner();
}
showSpinner() just hides save/cancel buttons and shows a spinner in its place.
hideSpinner() does the opposite.
saveState() saves the data from input fields to their data attributes.
settings.onSave() can be whatever code is passed in to the config by a user of the plugin.
When I run the process the spinner never shows up even though the hook-in I have defined takes ~1.5 seconds to return. If I pause the code in the debugger, the spinner does have a chance to show and it does disappear after the operation is complete.
What is the best approach to resolve this? I am not at all familiar with asynchronous design patterns within javascript. I know there is a single thread that the javascript can run on but I don't know why the save operation is getting in the way of showing the spinner.
Your browser won't update the interface until Javascript gives back control to the browser, meaning you need to return from function before the browser will show the spinner. Use setTimeout to give control back to the browser briefly.
function save(){
showSpinner();
setTimeout(function(){
var settings = getSettings();
// Hook-in call
if(settings.onSave)
settings.onSave();
saveState();
removeSpinner();
}, 0 );
}

Categories

Resources