Question About Order of Execution of Functions in React - reactjs

In the following code, why is the sleep function executed before the startClock function?
handleClick = () => {
this.startClock();
this.sleep(5000);
}
startClock = () => {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
// add a zero in front of numbers<10
m = this.checkTime(m);
s = this.checkTime(s);
document.getElementById("txt").innerHTML = h + ":" + m + ":" + s;
console.log(h + ":" + m + ":" + s);
var t = setTimeout(function(){this.startClock()}.bind(this), 1000);
};
checkTime = (i) => {
if (i < 10) {
i = "0" + i;
}
return i;
};
sleep = (timeout) => {
var begin = new Date();
while (new Date() - begin < timeout) {
}
};
I would expect the startClock function to execute first but the sleep function executes first and then the startClock function.

I think what is actually happening here is the startClock function is executed first but since the time specified in setTimeout is 1000ms, the sleep function starts before the GUI is updated and therefore the GUI is not updated until sleep is finished.

Related

React hooks - Update State in function

hi i have an issue with set state , i write the function that i get Position x,y and size of width , height(That is the name of the state that holds them POx1, POY1, widthSize, heightSize) and depend on user choise, i change the state's that user get to me and Use them. but after the first setSate for all these State i can't update and or change them . these are my code's:
function DrawPicture() { // this function call after click
setCountClick(CountClick + 1);
var Se_image = new Image();
Se_image.src = ImgSRC;// (ImgSRC) is the State i define it before
Se_image.onload = function () {
ctxRef.current.globalCompositeOperation = "source-over";
if (CountClick === 2) {// For some reason, I want this condition to be executed after calling the above function twice
var img = Se_image
PictureCategory(img) // This function is shown below
var canvas = canvasRef.current
var ctx = canvas.getContext('2d');
var imageData = ctx.getImageData(POx1, POY1, widthSize, heightSize);
var data = imageData.data;
console.log(lineColor);
const r = parseInt(lineColor.substr(1, 2), 16)
const g = parseInt(lineColor.substr(3, 2), 16)
const b = parseInt(lineColor.substr(5, 2), 16)
var changeColor = function () {
for (var i = 0; i < data.length; i += 4) {
data[i] = r
data[i + 1] = g
data[i + 2] = b
}
ctx.putImageData(imageData, POx1, POY1);
};
changeColor();
setCountClick(1);
setPointer(false);
}
}
}
and this is my PictureCategory() function:
For convenience, I only took one of the modes
function PictureCategory(image) {
switch (PictureTopic) {
case "Girl":
const XG = POx1 - (0.5 * widthSize) < 0 ? 0 : POx1 - (0.5 * widthSize);
const newWidth= 2.4*widthSize;
const newheight= 2.5*widthSize;
setPOx1(XG)
setwidthSize(newWidth)
setheightSize(newheight)
ctxRef.current.clearRect(XG, POY1, newWidth, newheight);
ctxRef.current.drawImage(image, XG, POY1, 2.4 * widthSize, 2.5 * heightSize);
break;
default:
ctxRef.current.drawImage(image, POx1, POY1, widthSize, heightSize);
break;
}
}
i want to change state's with above function please help me !!!
Not sure if it'll fix your issue, but the following has to be done in any case.
It should be
setCountClick(countClick=> countClick + 1);
When state is updated using its previous value, the callback argument of the state setter should be used.
See https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous
i know it's not your answer for this question. but you can use this codes for have new value .
I stored the new values in an object and returned them:
function DrawPicture() {
setCountClick(CountClick + 1);
var Se_image = new Image();
Se_image.src = ImgSRC;
Se_image.onload = function () {
ctxRef.current.globalCompositeOperation = "source-over";
if (CountClick === 2) {
var img = Se_image
const Sizes =PictureCategory(img) // you can store new value in valible
var canvas = canvasRef.current
var ctx = canvas.getContext('2d');
var imageData = ctx.getImageData(Sizes[0].x, Sizes[0].y, Sizes[0].width, Sizes[0].height);
var data = imageData.data;
console.log(lineColor);
const r = parseInt(lineColor.substr(1, 2), 16)
const g = parseInt(lineColor.substr(3, 2), 16)
const b = parseInt(lineColor.substr(5, 2), 16)
var changeColor = function () {
for (var i = 0; i < data.length; i += 4) {
data[i] = r
data[i + 1] = g
data[i + 2] = b
}
ctx.putImageData(imageData,Sizes[0].x, Sizes[0].y);
};
changeColor();
setCountClick(1);
setPointer(false);
}
}
}
function PictureCategory(image) {
switch (PictureTopic) {
case "Girl":
const XG = POx1 - (0.5 * widthSize) < 0 ? 0 : POx1 - (0.5 * widthSize);
const newWidth= 2.4*widthSize;
const newheight= 2.5*widthSize;
ctxRef.current.clearRect(XG, POY1, newWidth, newheight);
ctxRef.current.drawImage(image, XG, POY1, 2.4 * widthSize, 2.5 * heightSize);
return[{x: XG,y:POY1,width:newWidth,height:newheight}]
default:
ctxRef.current.drawImage(image, POx1, POY1, widthSize, heightSize);
break;
}
}

Creating a javascript array to localstorage not returning desired result

I'm trying to create an array to localstorage containing some gear box values, witch I then need again to do some more calculations with specific array[?].value.
The problem I'm encountering is that the created entry returns only 2 array entries, although all entries are there but the " is at the beginning and then at the second last entry and then before and after the last entry.
These are the values generated.
spd_Dev = ["202.391,172.876,120.451,102.601,85.173,72.664,61.701,52.706,45.116,38.510,32.326,27.407,22.910,19.536,16.585,14.195,12.228","10.401"]
When I used to use a fixed array I've entered it as:
var spd_Dev = [202.391, 172.876, 120.451, 102.601, 85.173, 72.664, 61.701, 52.706, 45.116, 38.510, 32.326, 27.407, 22.910, 19.536, 16.585, 14.195, 12.228, 10.401];
So my question is how to write this values to localstorage and read again from localstorage so that I can use this values as an array.
This is what I'm trying to work.
var D_RatioId = data.truck.make + data.truck.model + "D_Ratio"
var G_RatioId = data.truck.make + data.truck.model + "G_Ratio"
var fGr = data.truck.forwardGears;
var gr = data.truck.displayedGear;
var Rpm = data.truck.engineRpm * 100;
var spd = data.truck.speed;
var T_Dia = 1008.3;
if (localStorage.getItem(G_RatioID) == undefined) {
localStorage.setItem(G_RatioID, '');
var fG_Rat = [localStorage.getItem(G_RatioID)];
} else {
var fG_Rat = [localStorage.getItem(G_RatioID)];
}
var spd_Dev = localStorage.getItem(Spd_DevId);
spd_Dev = spd_Dev ? spd_Dev.split(', ') : [];
if (localStorage.getItem("i") == undefined) {
localStorage.setItem("i", 1);
var i = localStorage.getItem("i");
} else {
var i = localStorage.getItem("i");
}
if (i <= fGr && spd > 0.5) {
if (i <= fGr + 1) {
if (i == gr) {
if (RPM > 1450) {
var G_Ratio = Math.abs(Rpm / D_Ratio * (Math.PI * T_Dia / 1000) * 60 / spd / 1000, 2).toFixed(2);
var spd_D = Math.abs(RPM / (RPM / G_Ratio / D_Ratio * (Math.PI * T_Dia / 1000) * 60 / 1000) * 0.821932).toFixed(3);
fG_Rat.push(G_Ratio);
spd_Dev.push(spd_D);
i++;
localStorage.setItem("i", i);
var G_RatioValue = fG_Rat;
var Spd_DevValue = spd_Dev;
SetG_Ratio(G_RatioID, G_RatioValue);
SetSpd_Dev(Spd_DevId, Spd_DevValue);
localStorage.setItem("spd_Dev", JSON.stringify(Spd_DevValue));
}
}
}
}
function SetG_Ratio(G_RatioID, G_RatioValue) {
localStorage.setItem(G_RatioID, G_RatioValue);
console.log(G_RatioID, G_RatioValue);
}
function SetSpd_Dev(Spd_DevId, Spd_DevValue) {
localStorage.setItem(Spd_DevId, Spd_DevValue.toString());
console.log(Spd_DevId, Spd_DevValue, Spd_DevValue.length);
}
if (spd >= 0) {
var spd_Dev = [localStorage.getItem(Spd_DevId)];
var spD_D = JSON.parse(spd_Dev);
for (i = 1; i < (fGr + 1); i++) { // Some more code dependant on the above results //
why don't you use LSM.js? it will make everything simpler. you can put the array as an array so that it will return the full array only, you will not need to use split(),
https://github.com/kevinj045/LSM_js
var lsm = new LSM("G_RatioID");
var G_RatioValue ["202.391,172.876,120.451,102.601,85.173,72.664,61.701,52.706,45.116,38.510,32.326,27.407,22.910,19.536,16.585,14.195,12.228","10.401"];
lsm.set("G_RatioID",G_RatioValue);
console.log(lsm.get("G_RatioID")); // it will return the full array

Is there a way that I can change the frequency of $interval dynamically

I came up with this Typescript code to check connectivity. It does a check every 60 seconds to confirm connectivity. I would like to make it so that the connection checks are more frequent if the connection is lost. Is there some way I could do this? I think it would mean changing the time interval but I am not sure how to do this once the $interval is started and running.
isConnected = (): ng.IPromise<any> => {
return this.$http({
method: 'GET',
url: self.ac.dataServer + '/api/Connect/Verify',
ignoreLoadingBar: true
} as ng.IRequestConfig);
};
openConnectionHandler = () => {
var self = this;
self.minutes = 0;
self.mos.closeConnectionModal()
}
closeConnectionHandler = () => {
var self = this;
if (self.minutes == 0) {
self.connectionModalBody = "Unable to establish a connection to the " + self.shortDomainName + " server";
} else if (self.minutes == 1) {
self.connectionModalBody = "Unable to establish a connection to the " + self.shortDomainName + " server for " + self.minutes + " minute.";
} else {
self.connectionModalBody = "Unable to establish a connection to the " + self.shortDomainName + " server for " + self.minutes + " minutes.";
}
self.minutes++;
self.mos.openConnectionModal();
}
checkConnection = () => {
var self = this;
self.isConnected().then(self.openConnectionHandler, self.closeConnectionHandler);
this.$interval(function () {
self.isConnected().then(self.openConnectionHandler, self.closeConnectionHandler);
}, 60 * 1000);
}
In my application controller I make this call when the application starts:
uss.checkConnection();
Yes there is a way. You cancel your current interval and create a new one with a different timeout value.
Example:
//here is where your interval initialization
var intervalPromise = $interval(intervalWhenConnectionIsUp, 60*1000);
function intervalWhenConnectionIsUp(){
//your stuff goes here
//let's say there is a variable which we can use to identify connection failures
if(connectionFailed){
//just cancel the current interval by the `cancel` method
intervalPromise.cancel();
//and set the proper interval function
intervalPromise = $interval(intervalWhenNoConnection, 30*1000)
}
}
function intervalWhenNoConnection(){
//your stuff goes here
if(connectionIsUp){
//just cancel the current interval by the `cancel` method
intervalPromise.cancel();
//and set the proper interval function
intervalPromise = $interval(intervalWhenConnectionIsUp, 60*1000)
}
}
You can set-interval inside another function which takes a parameter as timeout for the $interval. And call this function with desired time interval.
Here is angularish code with no global variable
function MyCtrl($scope, $interval) {
var intervalInstance;
function onNoConnection() {
checkConnectionAtRate(30*1000);
}
function checkConnectionAtRate(rate) {
if (angular.isDefined(intervalInstance)) {
$interval.cancel(intercalInstance);
}
intervalInstance = $interval(function() {
//here goes the code;
console.log('Something');
}, rate);
}
function checkConnection() {
checkConnectionAtRate(60 * 1000);
}
}
UPDATE 2 to fit problem statement (not sure about typescript syntax)
openConnectionHandler = () => {
//same code
}
closeConnectionHandler = () => {
//same code
self.checkConnectionAt(30*1000);
}
checkConnection = () => {
var self = this;
self.checkConnectionAt(60 * 1000);
}
checkConnectionAt = (rate) => {
var self = this;
if(self.intervalInstance) {
$interval.cancel(self.intervalInstance);
}
self.intervalInstance = $interval(function () {
self.isConnected().then(self.openConnectionHandler, self.closeConnectionHandler);
}, rate);
}

clearInterval after 10sec doesnt work

I created a little Game and that should create every 1sec a enemy till there are 10 enemy (10sec)
if i do it without clearInterval it creates the whole time enemys
so i want to stop when it reach 10
var initEnemy = function ()
{
//enemy div
for(var i = 0; i < 10; i++)
var timerid = null;
function IntervalFunction()
{
var randomX = Math.floor(Math.random() * 190);
var randomY = Math.floor(Math.random() * 50);
enemy.push(new Enemy(randomX, randomY).create());
}
IntervalFunction();
setInterval(IntervalFunction,1000);
clearInterval(IntervalFunction),10000);
}
clearInterval doesn't take second argument.
And setTimeout is easier to wrap head around... A simple approach is to count how many enemies you've created so far and not run setTimeout when the limit is reached:
var initEnemies = function () {
var numEnemiesCreated = 0;
function createAnotherEnemy() {
var randomX = Math.floor(Math.random() * 190);
var randomY = Math.floor(Math.random() * 50);
enemy.push(new Enemy(randomX, randomY).create());
numEnemiesCreated += 1;
if (numEnemiesCreated < 10)
setTimeout(createAnotherEnemy, 1000);
}
createAnotherEnemy();
}
And a version with for loop, it schedules function calls 0s, 1s, 2s, ... , 9s from now:
var initEnemies = function () {
function createEnemy() {
var randomX = Math.floor(Math.random() * 190);
var randomY = Math.floor(Math.random() * 50);
enemy.push(new Enemy(randomX, randomY).create());
}
for (var i=0; i < 10; i++)
setTimeout(createEnemy, i * 1000);
}
update
Here's a version with setInterval and clearInterval. You still have to count how many enemies you've created so far, and you have to use interval id in clearInterval call. Haven't tested this, sorry!
var initEnemies = function () {
var numEnemiesCreated = 0;
var intervalId;
function createEnemy() {
var randomX = Math.floor(Math.random() * 190);
var randomY = Math.floor(Math.random() * 50);
enemy.push(new Enemy(randomX, randomY).create());
// Unschedule ourselves after 10th run
numEnemiesCreated += 1;
if (numEnemiesCreated == 10)
clearInterval(intervalId);
}
intervalId = setInterval(createEnemy, 1000);
}

Issues with using setTimeout inside of a for loop with arrays

--- UPDATE ---
Here is another attempt... The issue seems to be that the animation only happens to the third item in the for loop array I'm assuming because of the setTimeout delay. How can I have the animation fire for each item (3) with a delay?
// Breadcrumb Animation
(function(){
var header = document.getElementById("header"),
header2 = document.getElementById("header-secondary"),
banner = document.getElementById("banner");
var bcLink = [header, header2, banner];
var myTime = '';
var myItem = '';
function delay() {
setTimeout(fadeIn, myTime);
function fadeIn() {
if( myItem.style.opacity !== '1' ) {
console.log(myItem);
setInterval(function(){
myItem.style.opacity = parseFloat(myItem.style.opacity) + 0.1;
}, 100);
}
}
}
var i, len=bcLink.length;
for(var i = 0; i < len; i++) {
bcLink[i].style.opacity = 0;
myItem = bcLink[i];
myTime = myTime = parseInt(myTime + 2000)
delay();
}
})();
--- END UPDATE ---
The code below works but I was trying to optimize my code by creating a foor loop that will loop through each of the items (my attempt is commented out). I'm currently using 3 items on my page (header, header2, banner) that will load one after the other, but the second should not start until the first loads, the third should not start until the second item loads, and so on. This code will eventually be used for breadcrumbs where the amount of items will be uncertain but they will still load one after the other. Any help is greatly appreciated.
(function(){
var header = document.getElementById("header"),
header2 = document.getElementById("header-secondary"),
banner = document.getElementById("banner");
var bcLink = [header, header2, banner];
var myTime = '';
function fadeIn(name, speed) {
if( name.style.opacity !== '1' ) {
setInterval(function(){
name.style.opacity = parseFloat(name.style.opacity) + 0.1;
}, speed);
}
}
function delay(funct, time) {
setTimeout(function() {funct}, time);
}
bcLink[0].style.opacity = 0;
bcLink[1].style.opacity = 0;
bcLink[2].style.opacity = 0;
setTimeout(function(){fadeIn(bcLink[0], 100)}, 0);
setTimeout(function(){fadeIn(bcLink[1], 100)}, 1000);
setTimeout(function(){fadeIn(bcLink[2], 100)}, 2000);
// for(var i = 0; i < bcLink.length; i++) {
// bcLink[i].style.opacity = 0;
// delay(fadeIn(bcLink[i],100), i + 000);
// }
})();
use jQuery animation queue, not timeout.
http://blog.bigbinary.com/2010/02/02/understanding-jquery-effects-queue.html
Try changing:
delay(fadeIn(bcLink[i],100), i + 000);
to:
setTimeout(function(){fadeIn(bcLink[i], 100)}, i * 1000);

Resources