how to stop other code from executing while set timeout is executing? - javascript

This question is duplicate of How to stop other code from running until setTimeout() finishes running?
In the above question the person does not want any code to be executed until the setTimeout function has been executed. So that function never get executed. But here in my case I want the code after the setTimeout to execute.(after setTimeout has finished executing)
BUt it's not working for me. Here is the code :
console.log("Hello Wolrd");
var prev_exe = false;
setTimeout(function(){
console.log("Hello Again");
prev_exe = true;
}, 3000)
function bye() {
if(!prev_exe) {
return;
}
console.log("Gud Bye");
}
bye();
I expect the output to be :
Hello wolrd
Hello again
gud bye
But that is not happening, instead the code just run the first tow console.log() statements and the third is ignored.
Pls help me understand what is wrong with my code .

You don't want to stop other code from running, you want to make other code wait to run - so the if (!prev_exe) { return isn't the logic you need, since that'll mean Gud Bye never gets logged.
Consider constructing a Promise from the timeout instead, and call .then on it:
console.log("Hello Wolrd");
const againProm = new Promise((resolve) => {
setTimeout(function(){
console.log("Hello Again");
resolve();
}, 3000);
});
function bye() {
console.log("Gud Bye");
}
againProm.then(bye);

Related

How to abort function by timeout at JavaScript

I need to execute some function but if timeout expired I need to abort this function. I tried to use setTimeout and setImmediate. I wrote this example and used setInterval in callback for checking of working but it did't help me:
function waiter(timeout, fun) {
var functionHandler = setImmediate(fun);
var timeoutHandler = setTimeout(() => {
console.log('stoped');
clearImmediate(functionHandler);
clearTimeout(timeoutHandler);
}, timeout);
fun();
}
waiter(5000, () => {
setInterval(() => {
console.log('work');
}, 500);
});
After clearImmediate and clearTimeout my interval still working. How I understood that method doesn't guarantee that my function will be aborted.
Does anybody have an idea how to abort function execution?
UPDATE:
Yes, I know that I should call clearInterval but it's just an example for work checking. For example I should parse some big data and if it doesn't can do it by timeout I need to cancel this function execution and call something else.
The clearXXX functions don't abort functions that are currently running, they just remove functions from the async queue, so that they never start to run. JavaScript always executes code to its completion. You cannot interrupt code that's running in the main thread.
You need to name your interval
and clear it by its name. So your interval is no longer anonymous, but you've got a reference for it.
let counter = 10;
let newYearCountdown = setInterval( () => {
console.log(counter);
counter--
if (counter === 0) {
console.log("HAPPY NEW YEAR!!");
// here i clear interval by its name.
clearInterval(newYearCountdown);
}
}, 1000);

Stopping current operation and proceed to another (new) operation

function windowResize() {
someFunction();
console.log("test3");
}
function someFunction(){
console.log("test");
longExecutingFunctionWithAsyncReq();
console.log("test2");
}
function longExecutingFunctionWithAsyncReq() {
// some codes here
}
whenever the window is resize(zoomed out/in), this function is called.
But if the user spams the zoom, someFunction() will not have the time to finish and will then cause the error.
I'm thinking of addressing this issue by stopping the current operation and then process the new operation. Also, I've tried reading about Deferred and Promise, but I can't grasp the simplicity of the topic and I'm not sure if it really solves my problem. Plus, I've also checked on callbacks and was very doubtful that this will not solve my problem either.
If my solution is not possible though, I thought of just queuing the operations, but the downside might be, the queue might overflow if not controlled. As for this solution, I've not looked any farther to this, except reading about it.
you could use a timeout and clear it before resetting it when the resize function is called:
var myTimeout;
function windowResize() {
clearTimeout(myTimeout);
myTimeout = setTimeout(someFunction, 500);
}
this way the function will be called when the user stops resizing and 500 miliseconds have passed.
if you just need to wait for operation to finish you can set up a flag.
var working = false;
function windowResize() {
if (!working){
working = true;
someFunction();
console.log("test3");
}
}
function someFunction(){
console.log("test");
longExecutingFunctionWithAsyncReq();
console.log("test2");
}
function longExecutingFunctionWithAsyncReq() {
// some codes here
// on finish set working to False
}
var isStillWorking = false;
function windowResize() {
if(isStillWorking) {
// Do nothing.
} else {
someFunction(function(){
isStillWorking = false;
});
console.log("test3");
}
}
function someFunction(callback){
isStillWorking = true;
console.log("test");
longExecutingFunctionWithAsyncReq();
console.log("test2");
}
function longExecutingFunctionWithAsyncReq() {
// some codes here
}
To clarify more of Anton's answer I manage to implement the same thing using a flag [global] variable and a callback. I use a callback in order to flag=false since I also need to wait for the asynchronous requests inside the function to finish before resetting the flag.

Output of one sample program of javascript is giving wrong answer

I was reading one book named 'Hands on node.js' by 'Pedro Teixiera'.
I was trying to execute one same program giving in that book that will call a function and that function is calling the same function recursively within some interval again and again.
But when I executed, it gives only one time '1' and stops
Please help me to figure it out why it is not able to call the same function again.
Sample program is as follows:
var schedule = function(timeout, callbackfunction) {
return {
start: function() {
setTimeout(callbackfunction, timeout)
}
};
};
(function()
{
var timeout = 10000; // 1 second
var count = 0;
schedule(timeout, function doStuff() {
console.log(++ count);
schedule(timeout, doStuff);
}).start(timeout);
})();
You aren't actually calling the function again. start() is the part that starts the timer.
schedule( timeout, function doStuff() {
console.log( ++count );
schedule( timeout, doStuff ).start(); // <--- added .start() here
}).start();
(Also note that the start() function doesn't take parameters.)
with some interval again and again
No, for that you would have used setInterval instead of setTimeout.
it gives only one time '1' and stops
Yes, your doStuff function doesn't put a new timeout. Your odd schedule function needs to be .start()ed!

Execute statement after return statement in Javascript

window.onbeforeunload = function() {
if (document.getElementById("parentpan").style.display == "block") {
return "You are logged out.";
Logout();
}
};
I want the logout() function to be called after the return statement, is it possible?
You can't execute anything after a return statement.
edit: the finally statement allows code execution after a return for cleanup purposes.
(This is a good example for an XY-Question: You are asking about Y while never telling us for what X you actually need it).
The best possible way and most efficient way is try, catch and finally
catch is optional in this
`try{
// do something
return;
} finally {
// call function after return
}`
https://youtu.be/Is_o_L-ZIS8 this is helpful for you
The return statement ends a function, you cannot execute code after it. You could do this:
ret = "You are logged out.";
Logout();
return ret;
What you need is to execute Logout asynchronously. This can be easily achieve in JavaScript by using the setTimeout function as others have said. Here's a method I commonly use to call functions asynchronously:
Function.prototype.async = function () {
setTimeout.bind(null, this, 0).apply(null, arguments);
};
This method pushes a function call onto the event loop immediately (after 0 ms). Hence the function is executed after the current code completes (which for you is after you return). Here's a simple example of how to use it:
alert.async("This will be displayed later.");
alert("This will be displayed first.");
Since the first alert is called asynchronously it will execute after the second call to alert. As simple as preceding your function call with async. This is what you would do in your case:
window.onbeforeunload = function () {
if (document.getElementById("parentpan").style.display === "block") {
Logout.async();
return "You are logged out.";
}
};
What's the disadvantage? Since the function is blocked on the event loop it may never get the chance to execute (hence the user will never logout). Such a situation may arise. It usually occurs when the control goes into an infinite loop, or hangs because of a blocking AJAX request.
Good news for you however, this happens on a very rare occasion. So don't worry about it. Just use setTimeout like everyone else is bantering you to and you'll do just fine. Personally I think you should log out before returning a message that "You are logged out.", but it's your application.
Happy New Year. Cheers!
In general if you want something to be executed after the function has returned, you can set a timer:
function myFunction() {
if (document.getElementById("parentpan").style.display == "block") {
setTimeout(Logout, 50); // Logout will be called 50ms later
return "You are logged out.";
}
};
However, as noted in comments, this is not a good idea for onbeforeunload, as the timer event will not be fired if the page finished unloading first.
Most of the other answerers are missing what you are trying to do here. You want window.onbeforeunload to act like window.confirm(). There is no way to act on the ok action in the onbeforeunload event.
What you would have to do is hook it up on onunload to do the action.
window.onbeforeunload = function () {
return "Your session will be logged out"
};
window.onunload = function () {
logout();
}
Problem with this is modern day browsers will kill a lot of processes that run in unload/beforeunload to "speed up" the browser so it is faster. So if it is asynchronous, you will have a race condition.
return means you are returning from the execution of the called function.When return statement is executed, system understands that the function execution is over and it will switch to the main program from which the function is called.
In the program, you can see a statement after return.But the system wont check that even.
If you have jquery in your project you can use defered mechanism. You can return promise object for ongoing tasks like this :
function task() {
var defered = $.Deferred();
setTimeout(defered.resolve , 5000);
return defered.promise();
}
function task2() {
var defered = $.Deferred();
setTimeout(defered.resolve , 10000);
return defered.promise();
}
function run() {
return $.when(task(),task2());
}
var promise = run();
promise.done(function(){
alert("All tasks has been completed");
});
Demo
You can use setTimeout to achieve this. Your code should be as below
window.onbeforeunload = function() {
if (document.getElementById("parentpan").style.display == "block") {
setTimeout(function(){
Logout();
}, 0);
return "You are logged out.";
}
};
This will make sure that Logout is executed after return statement.
var a = 10;
function b(){
a = 25;
return;
function a(){}
}
b();
document.write(a);
try it
I found two ways to approach this.
The first one is as stated above by Bhavsar Japan
1. Example with try, catch and finally
const example1 = () => {
try {
return console.log('will execute first')
} finally{
console.log('will execute second')
}
return 'will never execute'
}
const main = () => {
const message = example1();
console.log(message)
}
main()
2. Example with Promise.resolve
const example2 = () => {
Promise.resolve()
.then(() => console.log('will execute after return'));
return 'will execute first'
}
const main = () => {
const message = example2();
console.log(message);
}
main();
I just written a way to return a result and then call a callback, like this:
function after_return(result, callback) {
function returner(resolve) {
if (!resolve) {
new Promise((res) => returner(res)).then(callback);
return result;
} else {
resolve();
}
}
return returner(undefined);
}
function main(a, b) {
return after_return(a + b, (_) => {
console.log("DONE");
});
}
console.log(main(5, 4));
I'm guessing that Logout is a time-intensive process and you want to provide feedback to the user before executing it:
setTimeout(Logout,1);
return "You are logged out.";

using setTimeout synchronously in JavaScript

I have the following scenario:
setTimeout("alert('this alert is timedout and should be the first');", 5000);
alert("this should be the second one");
I need the code after the setTimeout to be executed after the code in the setTimeout is executed. Since the code that comes after the setTimeout is not code of my own I can't put it in the function called in the setTimeout...
Is there any way around this?
Is the code contained in a function?
function test() {
setTimeout(...);
// code that you cannot modify?
}
In that case, you could prevent the function from further execution, and then run it again:
function test(flag) {
if(!flag) {
setTimeout(function() {
alert();
test(true);
}, 5000);
return;
}
// code that you cannot modify
}
I came in a situation where I needed a similar functionality last week and it made me think of this post. Basically I think the "Busy Waiting" to which #AndreKR refers, would be a suitable solution in a lot of situations. Below is the code I used to hog up the browser and force a wait condition.
function pause(milliseconds) {
var dt = new Date();
while ((new Date()) - dt <= milliseconds) { /* Do nothing */ }
}
document.write("first statement");
alert("first statement");
pause(3000);
document.write("<br />3 seconds");
alert("paused for 3 seconds");
Keep in mind that this code acutally holds up your browser.
Hope it helps anyone.
Using ES6 & promises & async you can achieve running things synchronously.
So what is the code doing?
1. Calls setTimeOut 1st inside of demo then put it into the webApi Stack
2. Creates a promise from the sleep function using the setTimeout, then resolves after the timeout has been completed;
3. By then, the first setTimeout will reach its timer and execute from webApi stack.
4. Then following, the remaining alert will show up.
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function demo() {
setTimeout("alert('this alert is timedout and should be the first');", 5000);
await sleep(5000);
alert('this should be the second one');
}
demo();
Just put it inside the callback:
setTimeout(function() {
alert('this alert is timedout and should be the first');
alert('this should be the second one');
}, 5000);
No, as there is no delay function in Javascript, there is no way to do this other than busy waiting (which would lock up the browser).
ES6 (busy waiting)
const delay = (ms) => {
const startPoint = new Date().getTime()
while (new Date().getTime() - startPoint <= ms) {/* wait */}
}
usage:
delay(1000)
You can create a promise and await for its fulfillment
const timeOut = (secs) => new Promise((res) => setTimeout(res, secs * 1000));
await timeOut(1000)
Here's a good way to make synchronous delay in your code:
async function yourFunction() {
//your code
await delay(n);
//your code
}
function delay(n) {
n = n || 2000;
return new Promise(done => {
setTimeout(() => {
done();
}, n);
});
}
Found it here Right way of delaying execution synchronously in JavaScript without using Loops or Timeouts!
setTimeout(function() {
yourCode(); // alert('this alert is timedout and should be the first');
otherCode(); // alert("this should be the second one");
}, 5000);
I think you have to make a promise and then use a .then() so that you can chain your code together. you should look at this article https://developers.google.com/web/fundamentals/primers/promises
You could attempt to replace window.setTimeout with your own function, like so
window.setTimeout = function(func, timeout) {
func();
}
Which may or may not work properly at all. Besides this, your only option would be to change the original code (which you said you couldn't do)
Bear in mind, changing native functions like this is not exactly a very optimal approach.

Categories