I have a function handle_response that has 2 outcomes directed using an if statement. Here is the code:
function handle_response(response) {
if (response["unlocked"]) {
activate_slider();
// ideally reset_slider() comes here
} else {
error(response["message"]);
reset_slider();
}
}
function activate_slider() {
setLocked(false);
setTimeout(function () {
setLocked(true);
reset_slider();
}, 3000)
}
I'd like to move reset_slider() out from activate_slider() and into the body of the if statement, so that it becomes analogous to the reset_slider() in the else statement which reads better. But I'm unsure how to do so because TWO functions depend on setTimeout (i.e., if there were just reset_slider(), then I'd just put in the if body setTimeout( reset_slider(), 3000).
Also suggestions on better abstractions welcome!
You're executing the setTimeOut method, so, an async process will be executed in the future.
Hence, the only way to extract the call of reset_slider is trough callback functions:
function handle_response(response) {
if (response["unlocked"]) {
activate_slider(reset_slider); // ideally reset_slider() comes here
} else {
error(response["message"]);
reset_slider();
}
}
function activate_slider(cb) {
setLocked(false);
setTimeout(function () {
setLocked(true);
cb();
}, 3000)
}
I was cleaning up my code and ran into a little trouble with callbacks, specifically getting the correct values to output when a callback is called. Could some explain to me why the following code spits out something that I'm not expecting and a possible solution without having to put in another parameter of i to the run() function, or is passing in i to know my index upon calling the callback the only way to do this?
for (var i in dls) {
run(dls[i][0], dls[i][1], function(isTrue){
if (isTrue) {
// Do true stuff here
} else {
console.log("Value is: " + dls[i][3])
}
});
}
Calling run() actually has the correct inputs inside, but upon that function calling the callback and going into the else statement, dls[i][3] spits out the same value i times.
I've tried putting different scopes around (run()) and such but to no avail and can't seem to wrap my head around this.
Thanks
EDIT:
If I wanted to split it up into a separate function, how would I do it?
var run = function(cb){
setTimeout(function() {
cb(false)
}, 3000);
}
for (var i in dls) {
run(dls[i][0], dls[i][1], (function(index) {
return extraction
})(i));
}
function extraction(isTrue){
if (isTrue) {
// stuff
} else {
console.log("Nothing changed in " + dls[i][3])
}
}
Here dls[i][3] is still incorrect and prints the same value 3 times.
You have fallen into the traditional "loop trap"
When it comes time for your callback to run i is now a different value.
What you can do is cache that value in another wrapper function:
for (var i in dls) {
run(dls[i][0], dls[i][1], (function (currentIndex) {
return function(isTrue){
if (isTrue) {
// Do true stuff here
} else {
console.log("Value is: " + dls[currentIndex][3])
}
};
})(i));
}
In regards to the edit / second question, assuming this is what you wanted to do:
// note that I changed the function signature of `run`
var run = function(val1, val2, cb) {
setTimeout(function() {
cb(false);
}, 3000);
};
// note the `wrapper` here
for (var i in dls) {
run(dls[i][0], dls[i][1], wrapper(i));
}
// this is the same as what the IIFE is doing,
// just with an external function instead
function wrapper(scopedIndex) {
// return a function to be used as the callback for `run`
return function extraction(isTrue) {
if (isTrue) {
// stuff
}
else {
// use the scoped index here
console.log("Nothing changed in " + dls[scopedIndex][3]);
}
}
}
Take a look at function makeExitCallback(i) in the other linked question, as well. It directly relates to what's going on here.
You should post what's in dls as well, just to make it easier to run your snippets locally.
This is the function in question
function matches_password(password)
{
var modified = false;
var matched = false;
User.count({password : password}, function (err, result)
{
modified = true;
console.log('hei');
if (err)
{
//error
}
else
{
if (result)
{
matched = true;
}
}
});
while (!modified)
{
console.log('sleeping');
sleep.usleep(100000);
}
return matched;
}
As you can see, I have a callback that updates some variables; the main flow of execution is delayed until the callback is fired. The problem is that 'hei' never appears in the console.
Removing the while loop fixes the problem, but I need it, or else matched is always false.
What's going on and what can I do to get around this setback?
It looks like you're running into a asynchronous issue. you could try using a setTimeout function inside your while loop that calls User.count(...)
for how setTimeout works with Node: How does setTimeout work in Node.JS?
I am trying to understand a JavaScript code.
Banana.reloadUser is being called inside a function without any arguments:
function(data) {
if (!data.result.success) {
alert(data.result.message)
} else {
/*do something*/
Banana.testData = data;
Banana.reloadUser();
}
}
Banana.reloadUser defined like this:
Banana.extend({
reloadUser: function(cb, data) {
var that = this,
done = function(d) {
$.extend(that.user, d);
if ($.isFunction(cb)) {
cb(d)
}
that.trigger("user.reloaded", [d])
};
if (data) {
done.apply(banana, [data])
} else {
/*do something*/
}
}
})
'reloaduser' is being called to save the userinfo data in the localstorage. So whenever user do something new from its account 'reloaduser' saves the new information into the localstorage.
My question is since Banana.reloadUser is being called without arguments how is it supposed to pick its arguments ?
Note: This is a part of a big JavaScript/jquery code so in case this information is not enough please ignore the question.
The big Javascript code does contain another function
Banana.reloadUser(function() {
try {
Banana.trigger('start', [$]);
}catch(e) { }
try {
$('[data-deferred]').deferredImage();;
}catch(e) { }
});
started = true;
};
If you call a JavaScript function without arguments then all its parameters receive a value of undefined (not null which is a different value).
So calling
Banana.reloadUser()
is just the same as:
Banana.reloadUser(undefined, undefined)
In your code this is perfectly ok, the condition:
if ($.isFunction(cb)) {
will fail because undefined is not a function, and later on the condition:
if (data) {
will also fail because undefined is treated as equivalent to false when it appears somewhere that a boolean value is expected.
It is exactly similar to the below call,
Banana.reloadUser(undefined,undefined);
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.";