I don't understand how this javascript function executes - javascript

When I run the following codes, the alert popup displays undefined. I thought it would return either true or false instead. Please can someone explain how the checkLoginStatus() function excutes. Thanks.
function checkLoginStatus() {
$.get("func.php", {op:'login_status', r:Math.random()}, function(data) {
if (data == "Yes") {
showSalesView();
return true;
} else {
loginView();
return false;
}
});
}
alert(checkLoginStatus());

There's a couple things wrong.
One, you're performing an asynchronous call within the function, so by the time the call has come back, checkLoginStatus has already returned. It essentially looks like this:
function checkLoginStatus() {
$.get("func.php", {
op: 'login_status',
r: Math.random()
}, function(data) {
if (data == "Yes") {
showSalesView();
return true;
} else {
loginView();
return false;
}
});
// return undefined
}
Second, you're returning within the callback of another function, so that return affects the return value of the callback to $.get
You want to use callbacks. So,
function checkLoginStatus(callback) {
$.get("func.php", {
op: 'login_status',
r: Math.random()
}, function(data) {
if (data == "Yes") {
showSalesView();
callback(true);
} else {
loginView();
callback(false);
}
});
}
and then
checkLoginStatus(function(result) {
alert(result);
});

The AJAX call is asynchronous, so the function that you specify as callback will be executed when the response arrives. The code doesn't wait for the response to exit from the checkLoginStatus function.
You can use a callback method to display the result:
function checkLoginStatus(callback) {
$.get("func.php", {op:'login_status', r:Math.random()}, function(data) {
if (data == "Yes") {
showSalesView();
callback(true);
} else {
loginView();
callback(false);
}
});
}
checkLoginStatus(function(status){ alert(status); });

what you are seeing is the undefined (void) return from the .get() function,
notice carefully that .get function call contains another function as the third parameter ( first being the url, second being an anon object) that is the "callback" for the results of the .get function, this is called later when the results have been returned from the server.

The returned bool is being returned by the $.get functions callback, not checkLoginStatus.
function checkLoginStatus() {
$.get("func.php", {op:'login_status', r:Math.random()},
// Start Callback Function
function(data) {
if (data == "Yes") {
showSalesView();
return true;
} else {
loginView();
return false;
}
// End Callback Function
});
}

Related

Wait for an external JS function before continuing the same method

I have a simple JS function defined like this :
function firstFunction() {
$.ajax({
url: "/path/to/my/endpoint",
type: "GET"
}).done(function (data) {
localStorage.setItem("myItem", data);
});
}
Later on, I have another function defined like this :
function mySecondFunction() {
if(localStorage.getItem("myItem") == null) {
// Here I want to call firstFunction() and stop everything until it finishes
}
//Immediately use localStorage.getItem("myItem") for other purposes
//no matter I entered the if() or not
}
With a simple async: false in $.ajax, it works, but I've seen it's going to be deprecated and I want to avoid this solution.
Could you please suggest how to wait for mySecondFunction when entering my if() ?
I tried with $.when() but without success, maybe I did somehting wrong ?
I tried something like
function mySecondFunction() {
var deferred = $.Deferred();
if(localStorage.getItem("myItem") == null) {
$.when(firstFunction()).then(function () {
deferred.resolve();
})
}
else {
deferred.resolve();
}
//other instructions
}
But other instructions are called BEFORE the end of firstFunction()
Make firstFunction() return a promise.
function firstFunction() {
return new Promise((res, err) => {
$.ajax({
url: "/path/to/my/endpoint",
type: "GET"
}).done(function (data) {
localStorage.setItem("myItem", data);
res()
});
});
}
Make mySecondFunction aysnc.
async function mySecondFunction() {
if(localStorage.getItem("myItem") == null) {
await firstFunction();
}
localStorage.getItem("myItem")
...
}
This is how I would recommend you do this, since the ajax request wont block execution of other code, like button callbacks. Async/await and promises are hard to grasp at first, so here's some reading on how they work behind the scenes.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
Just change your if clauses with a while loop and call your firstFunction in that loop.
Example:
function mySecondFunction() {
while(localStorage.getItem("myItem") == null) {
firstFunction()
}
}

How to get a response from a called function?

I'd like to receive a response (true or false) from a called function to decide if the function should continue or stop. Look at the following code for better understanding:
function function1() {
function2(); // call function2
// after called function (here I need true or false, to decide if the function should stop or continue)
}
function function2() {
if (condition === value) {
// do something, give function1 a response to continue
} else {
// do something, give function1 a response to stop
}
}
Updated:
function function1() {
console.log('call function2');
function2(); // call function2
// after called function (here I need true or false, to decide if the function should stop or continue)
console.log('back from function2');
}
function function2() {
if (condition === false) {
console.log('condition === false');
return;
}
}
You don't need an else on the statement. check to see if your variable is false and if it is it will return if not the rest of your function will run automatically.
function function1() {
function2(); // call function2
// after called function (here I need true or false, to decide if the function should stop or continue)
}
function function2() {
if (condition === false) {
return;
}
}
If function2 is synchronous you can just return:
function function1() {
if(!function2()){
return
}; // call function2
// after called function (here I need true or false, to decide if the function should stop or continue)
}
function function2() {
if (condition === value) {
return true;
} else {
return false;
}
}
If function 2 does something asynchronous and expects a callback (one of the tags in your question) then it may be easier to write a function that will use function2 and returns a promise.
function function1(condition) {
console.log('calling function 2');
function2AsPromise(condition).then(function(
function2Result
) {
if (!function2Result) {
console.log('function 2 result is false');
return;
}
console.log('function 2 result is true');
});
console.log('exiting function 2');
}
function function2(condition, callback) {
setTimeout(function() {
if (condition) {
callback(true);
} else {
callback(false);
}
}, 2000);
}
function function2AsPromise(condition) {
return new Promise(function(resolve) {
function2(condition, resolve);
});
}
function1(false);
const function1 = check => {
if (check === false) {
return;
} else {
console.log("back from function2");
}
};
function1(false) // console.log doesn't run
function1(true) // console.log runs
make sure that you pass in a Boolean value.

Return value from asynchronous OR synchronous JavaScript request

The function below first performs a synchronous comparison test == 0, and if it passes, returns some content, and if it doesn't pass, performs an asynchronous request. My intent is for the later to return some other content such as "something from post callback", but know I am doing things way wrong. Without changing the Ajax request to synchronous, is it possible to do this?
var value = function (test) {
if (test == 0) {
return 'value is zero ';
} else {
return $.post('/echo/html/', {
html: 'false ',
delay: .5
}, function (r1) {
console.log('r1', r1);
return 'something from post callback';
})
.done(function (r2) {
console.log('r2', r2);
return 'something from done callback';
});
}
}(1);
console.log(value);
https://jsfiddle.net/o5kq8he6/2/
Since you are already returning a promise from the ajax call, then from your synchronous comparison, just return a resolved promise. Then, both code paths return promises that are resolved with the terminal value and the caller can use the same code to process the result no matter which way it works internally. This is a common design pattern for code that is sometimes synchronous and sometimes asynchronous.
var myFunc = function (test) {
if (test == 0) {
return $.Deferred().resolve('value is zero ');
} else {
return $.post('/echo/html/', {
html: 'false ',
delay: .5
}).then(function (r2) {
console.log('r2', r2);
// this will be the return value of the promise
return 'something from ajax finished';
});
}
};
myFunc(1).then(function(value) {
// value is here either way
});
FYI, it does not make sense in your $.post() to use both a success handler function AND a .done() handler. If you're going to return a promise from the function (which is my recommendation), then you should use only promise handlers, not the success callback.
You may also need to understand that it does nothing useful to return a value from the success handler of an ajax call. That return value just goes back into the asynchronous bowels of the ajax infrastructure and is never used by anything.
Make it all async:
var value = function (test, callback) {
if (test == 0) {
callback('value is zero ');
} else {
return $.post('/echo/html/', {
html: 'false ',
delay: .5
}, function (r1) {
console.log('r1', r1);
callback('something from post callback');
})
.done(function (r2) {
console.log('r2', r2);
callback('something from done callback');
});
}
}(1, function(result) { console.log(result); } );
You can simulate an async call for the others and then use a callback for all:
var value = function (test, callback) {
if (test == 0) {
callback('value is zero ');
} else {
return $.post('/echo/html/', {
html: 'false ',
delay: .5
}, function (r1) {
console.log('r1', r1);
callback('something from post callback');
})
.done(function (r2) {
console.log('r2', r2);
callback('something from done callback');
});
}
}(1, myCallback);
function myCallback(result) {
// here will the result be
}
You can also use setTimeout to actually make the sync calls behave as async calls in case you should need that.

Callback: "Object is not a function"

I am trying to use CoffeeScript to setup an AJAX callback function like so:
The Pattern
function doAjax(callback)
{
$.ajax(url, data)
.done(function(){
// ... do stuff here ...
callback(true);
}).fail(function(){
callback(false);
});
}
function doSomething()
{
doAjax(function(result){
if (result == true )
console.log('success');
else
console.log('failed');
});
}
I am using the following CoffeeScript to do this (this is within an object):
CoffeeScript
doAjax: (callback) ->
$.getJSON(url)
.done( (data) ->
if something == true
callback(true)
else
callback(false)
).fail( () ->
callback(false)
)
doSomething: () ->
this.doAjax(function:(result)->
if result == true
console.log "true"
else
console.log "false"
It results in the following compiled JavaScript like this:
Compiled JS
MyObject.prototype.doAjax = function(callback) {
return $.getJSON(url).done(function(data) {
if (something == true) {
callback(true); // <--- The error happens here
} else {
callback(false);
}
}).fail(function() {
callback(false);
});
};
MyObject.prototype.doSomething = function() {
return this.doAjax({
"function": function(result) {
var message;
if (result === true) {
return console.log("true");
} else {
return console.log("false");
}
}
});
};
And I get the error (at the marked line above):
Uncaught TypeError: object is not a function
What am I doing wrong in my CoffeeScript here?
change this
this.doAjax(function:(result)->
to this
this.doAjax((result)->
functions in coffeescript are declared with () ->. function:() -> creates an object with a property called function that contains the actual function
Actually you are trying to callback function to perform some operation after successful ajax call, but you are calling the object as function.Define some function and use it to callback.thank you, for further assistance please report to me.

How to write a non-blocking if statement in Node JS?

I have an if statement in php:
if ( $isTrue && db_record_exists($id)) { ... }
else { ... };
The first condition is a true / false boolean check.
The second condition calls a function to see if a row exists in a database table and returns true or false.
I want to rewrite this conditional in Node JS so that it is non-blocking.
I have rewritten db_record_exists as follows...
function db_record_exists(id, callback) {
db.do( "SELECT 1", function(result) {
if (result) { callback(true); }
else { callback(false); }
);
}
...but I can't see how to then incorporate this into a larger if statement, with the boolean check. For example, the following statement doesn't make sense:
if (isTrue and db_record_exists(id, callback)) {
...
}
What is the "node" way to write this?
Any advice would be much appreciated.
Thanks (in advance) for your help.
Check the variable first, then check the result of the async call inside the callback.
if (isTrue) db_record_exists(id, function(r) {
if (r) {
// does exist
} else nope();
});
else nope();
function nope() {
// does not exist
}
You will need to use callbacks for the if and the else part. Then "nest" the and-conditions:
if ($isTrue) {
db_record_exists(id, function(result) {
if (result)
doesExist();
else
doesntExist();
});
else
doesntExist();
For convenience, you could wrap all that in a helper function (and if you need it multiple times, put in a library):
(function and(cond, async, suc, err) {
if (cond)
async(function(r) { (r ? suc : err)(); });
else
err();
})($isTrue, db_record_exists.bind(null, id), function() {
…
}, function() {
…
});
Maybe this way?
function db_record_exists(id, callback) {
db.do( "SELECT 1", function(result) { callback(result ? true : false); });
}

Categories

Resources