Waiting for a get request to complete - javascript

Alright, so I am making something that will make an account. I have this function that checks if the username exists, and if it isn't it returns false.
Then I have another function calling it, but it is automatically going to the else statement and not waiting for the get request to complete. How would I make it wait until it gets a response?
var accountPassword = "accToGetTix"
function checkUsername(username){
$.get("http://www.roblox.com/UserCheck/DoesUsernameExist?username=" + username, function(data){
$( document ).ready(function() {
return data.sucess; // true = taken , false = not taken
});
});
};
function makeNewAccount(accountName){
if (checkUsername(accountName) == false){
signupWindow = window.open("http://www.roblox.com/login/signup.aspx");
signupWindow.$("#SignupUsername").val(accountName)
signupWindow.$("#SignupPassword").val(accountPassword)
signupWindow.$("#SignupPasswordConfirm").val(accountPassword)
signupWindow.$('#birthdayMonthSelect option[value="0"]').prop('selected', true)
signupWindow.$('#birthdayDaySelect option[value="0"]').prop('selected', true)
signupWindow.$('#birthdayYearSelect option[value="25"]').prop('selected', true)
signupWindow.$('.gender-circle').click();
} else {
return true; // true = account taken , false = not taken
}
}
makeNewAccount('asdf205m0');

You can achieve this by updating your code like following
function checkUsername(username, callback) {
$.get("http://www.roblox.com/UserCheck/DoesUsernameExist?username=" + username, function(data) {
callback(data.sucess); // true = taken , false = not taken
});
};
function makeNewAccount(accountName) {
checkUsername(accountName, function(response) {
if (response == false) {
signupWindow = window.open("http://www.roblox.com/login/signup.aspx");
signupWindow.$("#SignupUsername").val(accountName)
signupWindow.$("#SignupPassword").val(accountPassword)
signupWindow.$("#SignupPasswordConfirm").val(accountPassword)
signupWindow.$('#birthdayMonthSelect option[value="0"]').prop('selected', true)
signupWindow.$('#birthdayDaySelect option[value="0"]').prop('selected', true)
signupWindow.$('#birthdayYearSelect option[value="25"]').prop('selected', true)
signupWindow.$('.gender-circle').click();
} else {
return true; // true = account taken , false = not taken
}
});
}

You can't return from an async call. You need to use callbacks. A little refactor and you can make it work:
function checkUsername(username, callback){
$.get("http://www.roblox.com/UserCheck/DoesUsernameExist?username=" + username, function(data){
if (callback) callback(data.sucess); // true = taken , false = not taken
});
};
function makeNewAccount(accountName){
checkUsername(accountName, function(response) {
if (response === false) {
signupWindow = window.open("http://www.roblox.com/login/signup.aspx");
signupWindow.$("#SignupUsername").val(accountName)
signupWindow.$("#SignupPassword").val(accountPassword)
signupWindow.$("#SignupPasswordConfirm").val(accountPassword)
signupWindow.$('#birthdayMonthSelect option[value="0"]').prop('selected', true)
signupWindow.$('#birthdayDaySelect option[value="0"]').prop('selected', true)
signupWindow.$('#birthdayYearSelect option[value="25"]').prop('selected', true)
signupWindow.$('.gender-circle').click();
} else {
return true; // true = account taken , false = not taken
}
})
}

you will have to use the .done function, like that:
var accountPassword = "accToGetTix"
function checkUsername(username){
$.get("http://www.roblox.com/UserCheck/DoesUsernameExist", {
"username": username
}).done(function(data){
if (data.success) {
alert("this username already exists");
} else {
makeNewAccount(username);
}
});
};
function makeNewAccount(accountName){
if (checkUsername(accountName) == false){
signupWindow = window.open("http://www.roblox.com/login/signup.aspx");
signupWindow.$("#SignupUsername").val(accountName)
signupWindow.$("#SignupPassword").val(accountPassword)
signupWindow.$("#SignupPasswordConfirm").val(accountPassword)
signupWindow.$('#birthdayMonthSelect option[value="0"]').prop('selected', true)
signupWindow.$('#birthdayDaySelect option[value="0"]').prop('selected', true)
signupWindow.$('#birthdayYearSelect option[value="25"]').prop('selected', true)
signupWindow.$('.gender-circle').click();
} else {
return true; // true = account taken , false = not taken
}
}
you can find more information here: https://api.jquery.com/deferred.done/
I'm not sure about what your get call returns, so, if you'll have to adapt your code if needed. Use console.log(data), inside the .done function if needed too. :p
EDIT:
the $.get function in jQuery makes an Assynchronous http request to the specified URL. Assynchronous means that the code will not necessarily run in a linear order by waiting the request to complete in order to pass to the next code line.
The javascript code can be categorized in two types: Synchronous and Assynchronous. Let me show you an example.
This is a synchronous code:
function IWillRunFirst(){
console.log("first!");
}
IWillRunFirst();
alert("I am the second");
var someElement = $("#justAnElement");
someElement.addClass("foo");
console.log("finish");
//this results:
// "first!"
// "I am the second"
// "finish"
This code will run in the exactly same order that it was wrote. Now here an example of assynchronous code:
function IWillRunFirstButMyResponseWillGetLate(){
$.get("someUrl", {
"myUrlParameter": "foo"
}).done(function(requestResponse){
console.log("Howdy! Did I got late?");
});
}
IWillRunFirstButMyResponseWillGetLate();
alert("I am the second");
var someElement = $("#justAnElement");
someElement.addClass("foo");
console.log("finished");
The result of the above code can be:
"I am the second"
"finished"
"Howdy! Did I got late?"
Remember: Ajax calls are ALWAYS assynchronous ;)

I think the cleanest way is to use promises object through jquery deffered https://api.jquery.com/jquery.deferred/, along with it u need to use jquery $.get method which returns promises. https://api.jquery.com/jquery.get/.
I can share the code examples, but going through this concept will benefit you more .

Related

Cannot get timeout to work due to possible errors in callback structure

I am trying to use the following code to call a server process two time in a single button press operation. My requirements state that I need to try two times, and update the user that I a retrying. If either try works then I present a success message, if both fail then I tell them to 'Try again'.
As coded, the following code works. The only problem is that I would like each of the messages to appear for one second so that they can be read.
I have tried every combination of setTimeout(1000) and delay(1000) and it either had no effect, or hung at that point. I suspect that there is a logic flaw with my callback structure. Can someone please point out to me what I am doing wrong?
$(".infoMessage").text("Starting Open Process...");
var deferred = openATMRPC.openATMFirst();
deferred.addCallback(function(result){
if (result == "false") {
$(".infoMessage").text("Attempting Second try...");
var insideDeferred = openATMRPC.openATMSecond();
insideDeferred.addCallback(function(result) {
if (result == "false") {
$(".infoMessage").text("Try Again Later");
} else {
$(".infoMessage").text("Success 2");
}
})
} else if(result == "true"){
$(".infoMessage").text("Success 1");
}
}
)
Note: My server process returns a string of "true" or "false" whether it was successful or not.
Try this pattern , utilizing jQuery.Deferred()
$(function () {
$(".infoMessage").text("Starting Open Process...");
// included `trueFalse` argument , here , to display flow of results
// not certain if `openATMRPC.openATMFirst()` ,
// `openATMRPC.openATMSecond()` returns a `promise` object ?
// utilized same function applied to both `deferred` and `insideDeferred`
var deferred = function(trueFalse) {
// return value from response as `deferred.promise`
// within `setTimeout` , after `1000` ms (one second)
return new $.Deferred(function (dfd) {
setTimeout(function () {
$.post("/echo/html/", {
html: trueFalse
})
// `deferred.always` utilized here ,
// to catch either `success` or `fail` ,
// not certain about `error` (`fail`) callbacks ?
.always(function (data) {
dfd.resolve(data)
})
}, 1000);
// return `deferred.promise()` ,
// e.g., "true" , or "false"
return dfd.promise()
})
};
// `deferred()` function called with `"false"` argument
deferred("false").done(function (result) {
if (result == "false") {
$(".infoMessage").text("Attempting Second try...");
// `insideDeferred` = `deferred()` called with `"true"` argument
var insideDeferred = deferred("true");
insideDeferred.done(function (result) {
if (result == "false") {
$(".infoMessage").text("Try Again Later");
} else {
$(".infoMessage").text("Success 2");
}
})
} else if (result == "true") {
$(".infoMessage").text("Success 1");
}
})
});
jsfiddle http://jsfiddle.net/guest271314/vpy207t9/
$(function () {
$(".infoMessage").text("Starting Open Process...");
var deferred = function(trueFalse) {
return new $.Deferred(function (dfd) {
setTimeout(function () {
dfd.resolve(trueFalse)
}, 1000);
return dfd.promise()
})
};
deferred("false").done(function (result) {
if (result == "false") {
$(".infoMessage").text("Attempting Second try...");
var insideDeferred = deferred("true");
insideDeferred.done(function (result) {
if (result == "false") {
$(".infoMessage").text("Try Again Later");
} else {
$(".infoMessage").text("Success 2");
}
})
} else if (result == "true") {
$(".infoMessage").text("Success 1");
}
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="infoMessage"></div>

how to break execution and display error inside success of ajax?

I am using ajax call to check for some validation and then submitting the form normally by html. In my ajax call,
function checkId() {
var str = $("#formObj").serialize();
$.ajax({
type : "post",
data : str,
url : "checkForId.mt",
async : false,
success : function(txt) {
if (txt == "pass") {
return "true";
} else if (txt == "same") {
$("#errorMsgIdSame").removeClass("hidden");
return "false";
}
},
error : function() {
alert("Error");
}
});
}
If the control goes to "pass", execution should continue. If it goes to "same", the execution should stop.
I am calling this ajax method from some other method.
function validateForm() {
var isValid = true;
isValid = checkId();
if (!isValid) {
$("#errorMsg").removeClass("hidden");
}
return isValid;
}
this validatioForm is called on button click. Now ajax code is working but validateForm method is not taking the return of the ajax method.
Need direction on how to carry this out so that to capture the return from the ajax method and how to return from the ajax method.
If I understood your question correctly, you want to return the result of an inner function from an outer function. This definition of checkId does just that.
function checkId() {
var result;
var str = $("#formObj").serialize();
$.ajax({
type : "post",
data : str,
url : "checkForId.mt",
async : false,
success : function(txt) {
if (txt == "pass") {
result = true;
return;
} else if (txt == "same") {
$("#errorMsgIdSame").removeClass("hidden");
result = false;
return;
}
},
error : function() {
alert("Error");
}
});
return result;
}
An ajax call is asynchronous.
When you call ajax what is happening is that the ajax starts a new thread to do its task--a post in your case.
After that the code that called the ajax keeps going.
When the task that the ajax call is doing returns, it executes what ever is in its pass or fail sections depending on the task status.
So basically your checkId method completes and returns before the ajax is finished.
I would recommend triggering whatever you need the return value for from the success section or fail section like this:
success : function(txt) {
if (txt == "pass") {
newfunction(true);
} else if (txt == "same") {
$("#errorMsgIdSame").removeClass("hidden");
newfunction(false);
}
},
Edit:
function newfunction(passFail)
{
//Do something with variable passFail
}

calling jquery ajax function from javascript [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
jQuery ajax return value
How to return the response from an AJAX call from a function?
I have javascript. It loads data from database. I want to return true or false with respect to loading data. But I could not return it. My code has given bellow:
function CheckISRC() {
var url = "/TrackEdit/CheckISRC/" + $('#isrcid').val();
var isrc = $('#isrcid').val();
var result = false;
$.get(url, {
isrc: isrc
}, function (data) {
if (data == "true") {
result = true;
}
else {
result = false;
}
});
return result;
}
It always gives false result. Anyone has faced this kind of problem? 'Thanks advance'
If it's so important to use the function synchronously you can refactor it to:
function CheckISRC() {
var url = "/TrackEdit/CheckISRC/" + $('#isrcid').val();
var isrc = $('#isrcid').val();
var result = false;
$.ajax({
async: false,
success: function (data) {
if (data == "true") {
result = true;
}
else {
result = false;
}
},
data: { isrc: isrc }
});
return result;
}
As #ManseUK async is deprecated in jQuery 1.8 so if you want synchronous approach you should use older version.
The problem is that when you return result, It doesnt have value. because the ajax didn't finish its task. you make some callback function and when the result of ajax is returned from server, do what you want to.
Some thing like this:
function CheckISRC(Callback) {
var url = "/TrackEdit/CheckISRC/" + $('#isrcid').val();
var isrc = $('#isrcid').val();
var result = false;
$.get(url, {
isrc: isrc
}, function (data) {
if (data == "true") {
Callback(true);
}
else {
Callback(false);
}
});
}
function YourCallback(result) {
//...
}
The JQuery ajax functions are asynchronous. This means that when you initialise result to false, the result is set to true or false after the "return result;" line has run.
You can make the call synchronous but this is considered worse practice. You are often better off refactoring your code to allow for the asynchronous nature of the JQuery Ajax.
For example, where you previously had:
function myFunction() {
//Code before
var result = CheckISRC();
//Code after using result
}
you could have the following:
function myFunction() {
//Code before
CheckISRC();
}
function myFunction_callback(result) {
//Code after using result
}
where you call myFunction_callback in the success option of your ajax code like so:
function CheckISRC() {
var url = "/TrackEdit/CheckISRC/" + $('#isrcid').val();
var isrc = $('#isrcid').val();
$.get(url, {
isrc: isrc
}, function (data) {
myFunction_callback(data == "true");
});
}

What design pattern should I apply when checking multiple ajax request completion?

I have 3 ajax call in one function and checkAjaxCompletion which checks each ajax completion flag.
What the code below does is send multiple separate ajax calls and interval method checks completion flags to determine whether to proceed or keep interval. (I know clearInterval is not shown but the point is I want to use something other than interval)
Current code is:
function manyAjax() {
setInterval( function() { checkAjaxCompletion(); } , 200);
ajax1();
ajax2();
ajax3();
}
function ajax1() {
//send ajax request to server and if success set flag to 1. Default is 0. Error is 2.
}
function ajax2() {
//send ajax request to server and if success set flag to 1. Default is 0. Error is 2.
}
function ajax3() {
//send ajax request to server and if success set flag to 1. Default is 0. Error is 2.
}
function checkAjaxCompletion() {
if(ajax1_flag == 1 && ajax2_flag == 1 && ajax3_flag == 1) {
//everything went success, do some process
}
else if(ajax1_flag == 2 || ajax2_flag == 2 || ajax3_flag == 2) {
//some ajax failed, do some process
}
else {
//all ajax have not been completed so keep interval i.e. do nothing here
}
}
But I'm hesitating to depend on using interval function because calling it so often seem such waste of memory. There must be better way to do. I'm thinking if observer pattern can be applied here but would like to hear opinions.
It is observer-notifier, if you want to call it that - but each of your ajax calls will more than likely have a callback in javascript when they complete. Why not call checkAjaxCompletion() at the end of each of them, and do nothing if you're still waiting on others?
Dustin Diaz does a great job with this example.
function Observer() {
this.fns = [];
}
Observer.prototype = {
subscribe : function(fn) {
this.fns.push(fn);
},
unsubscribe : function(fn) {
this.fns = this.fns.filter(
function(el) {
if ( el !== fn ) {
return el;
}
}
);
},
fire : function(o, thisObj) {
var scope = thisObj || window;
this.fns.forEach(
function(el) {
el.call(scope, o);
}
);
}
};
The publisher:
var o = new Observer;
o.fire('here is my data');
The subscriber:
var fn = function() {
// my callback stuff
};
o.subscribe(fn);
To unsubscribe:
var fn = function() {
// my callback stuff
};
o.subscribe(fn);
// ajax callback
this.ajaxCallback = function(){
$.ajax({
type: "POST",
url: ajax.url,
data: {key: value},
async : !isAll,// false使用同步方式执行AJAX,true使用异步方式执行ajax
dataType: "json",
success: function(data){
if(data.status == 'successful'){
selfVal.parent().find('.msg').addClass('ok').html(msg.ok);
}else if(data.status == 'failed'){
checkRet = false;
selfVal.parent().find('.msg').removeClass('ok').html(msg.error);
}else{
checkRet = false;
}
return this;
}
});
}
return this;
Maybe you want to check your inputvalue callback ajax in your form;
You can view my website Demo, hope help you.
http://6yang.net/myjavascriptlib/regForm
Okay my idea was to make your own object that can handle sending an array of requests, keep a history of each request and do what i'm gonna call 'postProccessing' on each response, here is a probably very dodgy bit of code to hopefully demonstrate what I am thinking.
var Ajax = function() {
var request, callback, lst;
if (window.XMLHttpRequest) {
request = new XMLHttpRequest();
} else if (window.ActiveXObject) {
request = new ActiveXObject("Microsoft.XMLHTTP");
}
request.onreadystatechange = handleResponse;
this.history = [{}];
this.send = function(args) {
for (var i = 0; i < args.length; i++) {
if (args.url) {
request.open(args.type || 'GET', args.url);
}
request.send(args.data || null);
callback = args.callback;
lst++;
}
}
function handleResponse() {
var response = {
url: '',
success: true,
data: 'blah'
};
history.push(response);
if (postProccess()) {
callback();
}
}
function postProcess() {
if (this.history[lst].success) {
return true;
} else {
return false;
}
}
}

jquery function doesn't return values correctly

I have this function
$.fn.validate.checkValidationName = function(id) {
$.post("PHP/submitButtonName.php", {checkValidation: id},
function(data) {
if(data.returnValue === true) {
name = true;
} else {
name = false;
}
**console.log("name = "+name); **//this prints out "true"****
}, "json");
};
and this .click function that calls it. All the variables are declared outside this function so that they should be accessible by other functions
$('.submitBtn').click(function() {
//clears the array before re-submitting the click function
nameValues = [];
usernameValues = [];
emailValues = [];
name = false;
username = false;
email = false;
//for each of the input tags
$("input").each(function() {
//if the curent input tag has the class .name, .userpass, or .email
if(($(this).hasClass("name"))) {
nameValues.push($(this).val());
} else if(($(this).hasClass("userpass"))) {
usernameValues.push($(this).val());
} else if(($(this).hasClass("email"))) {
emailValues.push($(this).val());
}
});
//call the checkValidation function with the array "values"
$.fn.validate.checkValidationName(nameValues);
$.fn.validate.checkValidationUsername(usernameValues);
$.fn.validate.checkValidationEmail(emailValues);
console.log("name = "+name); //but this prints out "false"
console.log("username = "+username);
console.log("email = "+email);
if((name === "true") && (username === "true") && (email === "true")) {
alert("Everything checks out great");
} else {
alert("You missed one!");
}
});
When I click the link to trigger the first function, it returns the value as "true" inside the function, but when I console.log("name"+name); in the .click function after the function call, it prints out false.
Why is this? Do I need to return something from the checkValidatoinName function?
$.post is asynchronous, which means that it won't wait for the result to get back before proceeding. You're probably initializing name to true somewhere, and it's getting true the first time, but all the other times, it's false, because the AJAX from the first one finished and set it to false.
Try using $.ajax instead of $.post, and set async to false in the options. The $.post documentation shows the options that $.post would give to $.ajax.

Categories