$.each wait for promise from each object [duplicate] - javascript

This question already has answers here:
What is cleanest way to turn Array of JQuery Promises into a JQuery Promise of an Array?
(2 answers)
Closed 6 years ago.
I have another callback/promise issues :-)
I'm trying to implement a series of function each of the function are waiting for a return value from the next one.
I have an ajax call that returns a json on success, in the success
block i'm sending this json to an async function validation.
In validation() I'm loading a script and for each object I sending it to
availability function, i want to wait for the availability to complete and to return value, each value that is return is being
pushed to an array that i want to send it in the end.
I'm having trouble with the callback implementations.
var validArr = [];
function checkStory(callback) {
$.ajax({
url: "",
type: "GET",
data: "",
async: true,
headers: {
Accept: "application/json"
},
success: function(data) {
if (data.isDoc == true) {
_checkDoc(callback);
} else {
if (data.responseObj) {
validation(data.responseObj);
} else {
callback(data.count);
}
}
},
error: function(err) {
console.log("No books");
}
});
}
function validation(responseObj) {
getScript('books.js',
function() {
$.each(responseObj, function(_index, _value) {
var res = aviliabilty(_value);
if (res) {
validArr.push(_index, true);
} else {
validArr.push(_index, false);
}
});
//return after all objects completed execution
return validArr;
}
);
}
function aviliabilty(entry) {
DM.ct.get(entry, function(response) {
if (response) {
for (var idx = 0, adLen = response.ds.length; idx < adLen; idx++) {
var bk = response.ds[idx];
for (var creaIdx = 0, crea = bk.creatives.length; creaIdx < crea; creaIdx++) {
var creative = bk.creatives[creaIdx];
if (creative.type == "line") {
for (var mfIdx = 0, mfLen = creative.Files.length; mfIdx < mfLen; mfIdx++) {
var mediaFile = creative.Files[mfIdx];
if (mediaFile.type == "horror") {
return true;
}
}
} else if (creative.type != "horror") {
return false;
}
}
}
}
});
}
// a function to get the script asynchronously
function getScript(url, success) {
var script = document.createElement('script');
script.src = url;
var head = document.getElementsByTagName('head')[0],
done = false;
// Attach handlers for all browsers
script.onload = script.onreadystatechange = function() {
if (!done && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete')) {
done = true;
success();
script.onload = script.onreadystatechange = null;
head.removeChild(script);
}
};
head.appendChild(script);
}

Option 1:
use a callback -
validation(data.responseObj, function(){
})
function validation(responseObj, callback) {
//your code....
callback(validArr)
}
Option 2: Use Promises -
validation(data.responseObj).then(function(validArr){
});
function validation(responseObj, callback) {
var defer = Q.defer()
//your code....
defer.resolve(validArr)
return defer.promise
}

Related

jQuery runs in background, but not in foreground

I have this code fragment:
if(!encryption_state){
if(cKey=="" || cKey==null){
cKey=getKey(aid); //here we trying to obtain key
if(cKey!="" && cKey!=null && cKey!=undefined){
if(isJSON(jKey) && encryption_state){
var tjKey = JSON.parse(jKey);
tjKey[aid] = cKey;
jKey = JSON.stringify(tjKey);
}else{
jKey = json.stringify({aid: cKey});
}
encryption_state=true;
}
}
if(!encryption_state){
if(cKey=="" || cKey==null){
cKey=rndstr(32); //generate string
}
var arr = {};
if(isJSON(jKey)) arr = JSON.parse(jKey);
arr[aid] = cKey;
jKey = JSON.stringify(arr);
encryption_state = true;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
But when i call getKey(kaid) function:
function getKey(kaid){
$.ajax({
method: "POST",
url: "/?mod=key&fnc=syncKey",
data: {
aid: kaid
},
done: function(data) {
var tret = (JSON.parse(data)['msg']);
return tret;
}
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Browsers don't continue do function getKey(), they do next commands in parent function, i don't know why they ignore web server answer and don't let function return server response :(
in general, an ajax call is asynchronous. That means, a sequence like
var a = 0;
a = getAwithAjaxFromServer(...);
console.log(a);
will immediately print "0" while the ajax is still runnng.
Your entire logic with cleyand encryption_state has to be put into the done function:
if(!encryption_state){
if(cKey=="" || cKey==null){
cKey=getKey(aid);
}
}
and in your ajax:
function getKey(kaid){
$.ajax({
method: "POST",
url: "/?mod=key&fnc=syncKey",
data: {
aid: kaid
},
done: function(data) {
var tret = (JSON.parse(data)['msg']);
.... PUT ALL THE LOGIC HERE .....
}
});
}
You must understand asynchronous mechanism in javascript to continue calling ajax. There are a lot of resources and stackoverflow questions. For example: https://www.pluralsight.com/guides/front-end-javascript/introduction-to-asynchronous-javascript
So, you can convert the code so:
if(!encryption_state){
var serverKeyCallback = function(cKey) {
if(cKey!="" && cKey!=null && cKey!=undefined){
if(isJSON(jKey) && encryption_state){
var tjKey = JSON.parse(jKey);
tjKey[aid] = cKey;
jKey = JSON.stringify(tjKey);
}else{
jKey = json.stringify({aid: cKey});
}
encryption_state=true;
}
};
var localKeyCallback = function(cKey) {
if(!encryption_state){
if(cKey=="" || cKey==null){
cKey=rndstr(32); //generate string
}
var arr = {};
if(isJSON(jKey)) arr = JSON.parse(jKey);
arr[aid] = cKey;
jKey = JSON.stringify(arr);
encryption_state = true;
}
}
manageKey(cKey, aid, serverKeyCallback, localKeyCallback);
}
function manageKey(cKey, kaid, serverKeyCallback, localKeyCallback) {
if(cKey=="" || cKey==null) {
$.ajax({
method: "POST",
url: "/?mod=key&fnc=syncKey",
data: {
aid: kaid
},
done: function(data) {
var tret = (JSON.parse(data)['msg']);
serverKeyCallback(tret);
localKeyCallback(tret);
}
});
}
else {
localKeyCallback(cKey);
}
}
Defining two encapsulated pieces of code, one to execute after serverResponse, and the other to execute after the serverResponse or when you have the cKey locally stored. I haven't tested the code, but it must work as you expect.

When can use .then to use currently returned value?

I make a call to a function that makes an ajax call like this:
send.startMonitoring({'fetchMethod': 'notificationInterval', 'lastmodif':0}).then(function(value){
console.debug(value);
});
But the error I'm getting is this:
Uncaught TypeError: Cannot read property 'then' of undefined in
jquery
As in above, I'm calling startMonitoring function which is on another page and passing an object for it to make ajax call to the server. That function returns value from server and I want to be able to do something with it. That's why I'm trying to use .then to process the value returned.
Since I'm getting the above error, how could I modify it so that
returned value can be processed? Also how and when I can use .then()?
var interface = (function(config) {
return {
transporter: function(options) {
return config.ajax(options);
},
startMonitoring: function(options) {
var PERIOD_NOT_VISIBLE = 60000;
var PERIOD_VISIBLE = 5000;
var timer = 0;
var timestring = 0;
(function callThis(timestamp) {
interface.transporter(options).then(function(value) {
if (value[1].notification[0].output == null) {
timestring = value[1].notification[0].lastmodif;
console.log(timestring);
return value;
}
}).catch(function(e) {
});
timer = setTimeout(function(){
callThis();
if (interface.isMonitoring() == 0 ) {
clearTimeout(timer);
}
}, (document.hidden) ? PERIOD_NOT_VISIBLE : PERIOD_VISIBLE);
})();
}
};
})(settings);
This is how ajax calls made:
ajax: function(opt) {
var defaultData = settings.getDefaultDataset();
var self = this;
var opt = $.extend({}, defaultData, opt);
var output = [];
return new Promise(function(resolve, reject) {
token = window.es.token;
opt[token] = "1";
jQuery.ajax({
method: "POST",
url: self.system.path+"/index.php",
"data": opt,
error: function() {
reject('error');
},
success: function(result) {
output.push(opt, result);
resolve(output);
}
});
});
}
Change startMonitoring to accept and call a callback parameter
startMonitoring: function(options, callback) {
var PERIOD_NOT_VISIBLE = 60000;
var PERIOD_VISIBLE = 5000;
var timer = 0;
var timestring = 0;
(function callThis(timestamp) {
interface.transporter(options).then(function(value) {
callback(value);
}).catch(function(e) {
});
timer = setTimeout(callThis, (document.hidden) ? PERIOD_NOT_VISIBLE : PERIOD_VISIBLE);
})();
},
Tidy up ajax to remove the Promise constructor anti-pattern, and to use .then of the promise returned by jQuery.ajax
ajax: function(opt) {
var defaultData = settings.getDefaultDataset();
var opt = $.extend({}, defaultData, opt);
var output = [];
var token = window.es.token;
opt[token] = "1";
return jQuery.ajax({
method: "POST",
url: this.system.path + "/index.php",
"data": opt,
})
.then(function(result) {
output.push(opt, result);
return output;
});
}
Change how you call startMonitoring to pass in a callback function
send.startMonitoring({'fetchMethod': 'notificationInterval', 'lastmodif':0}, function callback(value){
console.debug(value);
});
In jQuery, you can use the $.Deferred() function. For example :
function startMonitoring() {
var deferred = $.Deferred();
jQuery.ajax({
url: your_url,
type: 'GET',
success: function (data) {
deferred.resolve(data);
},
error: function (error) {
deferred.reject(error);
}
});
return deferred.promise();
}
Then, you can call your function :
startMonitoring().done(function (data) {
//Went well
}).fail(function (error) {
//Error
});

JavaScript callback function when working withing a loop

This is what the code below does:
Goes to a table in a database and retrieves some search criteria I will send to Google API (the PHP file is getSearchSon.php)
After having the results, I want to loop around it, call the Google API (searchCriteriasFuc) and store the results in an array
The last part of the code is doing an update to two different tables with the results returned from Google API (updateSearchDb.php)
In my code, I am using setTimeout in a few occasions which I don't like. Instead of using setTimeout, I would like to properly use callback functions in a more efficient way (This might be the cause of my problem) What is the best way of me doing that?
$(document).ready(function() {
$.ajax({
url: 'getSearchSon.php',
type: 'POST',
async: true,
dataType: 'Text',
/*data: { }, */
error: function(a, b, c) { alert(a+b+c); }
}).done(function(data) {
if(data != "connection")
{
var dataSent = data.split("|");
var search_criterias = JSON.parse(dataSent[0]);
var date_length = dataSent[1];
var divison_factor = dataSent[2];
var length = search_criterias.length;
var arrXhr = [];
var totalResultsArr = [];
var helperFunc = function(arrayIndex)
{
return function()
{
var totalResults = 0;
if (arrXhr[arrayIndex].readyState === 4 && arrXhr[arrayIndex].status == 200)
{
totalResults = JSON.parse(arrXhr[arrayIndex].responseText).queries.nextPage[0].totalResults;
totalResultsArr.push(totalResults);
}
}
}
var searchCriteriasFuc = function getTotalResults(searchParam, callback)
{
var searchParamLength = searchParam.length;
var url = "";
for(var i=0;i<searchParamLength;i++)
{
url = "https://www.googleapis.com/customsearch/v1?q=" + searchParam[i] + "&cx=005894674626506192190:j1zrf-as6vg&key=AIzaSyCanPMUPsyt3mXQd2GOhMZgD4l472jcDNM&dateRestrict=" + date_length;
arrXhr[i] = new XMLHttpRequest();
arrXhr[i].open("GET", url, true);
arrXhr[i].send();
arrXhr[i].onreadystatechange = helperFunc(i);
}
setTimeout(function()
{
if (typeof callback == "function") callback.apply(totalResultsArr);
}, 4000);
return searchParam;
}
function callbackFunction()
{
var results_arr = this.sort();
var countResultsArr = JSON.stringify(results_arr);
$.ajax({
url: 'updateSearchDb.php',
type: 'POST',
async: true,
dataType: 'Text',
data: { 'countResultsArr': countResultsArr },
error: function(a, b, c) { alert(a+b+c); }
}).done(function(data) {
var resultsDiv = document.getElementById("search");
if(data == "NORECORD") resultsDiv.innerHTML = 'Updated failed. There was a problem with the database';
else resultsDiv.innerHTML = 'Update was successful';
}); //end second ajax call
}
//llamando funcion principal
var arrSearchCriterias = searchCriteriasFuc(search_criterias, callbackFunction);
}
else
{
alert("Problem with MySQL connection.");
}
}); // end ajax
});
How you did it in 2015
Callbacks are things of the past. Nowadays you represent result values of asynchronous tasks with Promises. Here is some untested code:
$(document).ready(function() {
$.ajax({
url: 'getSearchSon.php',
type: 'POST',
async: true,
dataType: 'text'
/*data: { }, */
}).then(function(data) {
if (data == 'connection') {
alert("Problem with MySQL connection.");
} else {
var dataSent = data.split("|");
var search_criterias = JSON.parse(dataSent[0]);
var date_length = dataSent[1];
var divison_factor = dataSent[2];
return Promise.all(search_criterias.map(function(criteria) {
return $.ajax({
url: "https://www.googleapis.com/customsearch/v1"
+ "?q=" + criteria
+ "&cx=005894674626506192190:j1zrf-as6vg"
+ "&key=AIzaSyCanPMUPsyt3mXQd2GOhMZgD4l472jcDNM"
+ "&dateRestrict=" + date_length,
type: 'GET'
});
})).then(function(totalResultsArr) {
totalResultsArr.sort();
var countResultsArr = JSON.stringify(totalResultsArr);
return $.ajax({
url: 'updateSearchDb.php',
type: 'POST',
async: true,
dataType: 'text',
data: { 'countResultsArr': countResultsArr },
error: function(a, b, c) { alert(a+b+c); }
});
}).then(function(data) {
var resultsDiv = document.getElementById("search");
if(data == "NORECORD") {
resultsDiv.innerHTML = 'Updated failed. There was a problem with the database';
} else {
resultsDiv.innerHTML = 'Update was successful';
}
});
}
}).then(null, function() {
alert('Some unexpected error occured: ' + e);
});
});
This is how you do it in 2016 (ES7)
You can just use async/await.
$(document).ready(async() => {
try {
var data = await $.ajax({
url: 'getSearchSon.php',
type: 'POST',
async: true,
dataType: 'text'
/*data: { }, */
});
if (data == 'connection') {
alert("Problem with MySQL connection.");
} else {
var dataSent = data.split("|");
var search_criterias = JSON.parse(dataSent[0]);
var date_length = dataSent[1];
var divison_factor = dataSent[2];
var totalResultsArr = await Promise.all(
search_criterias.map(criteria => $.ajax({
url: "https://www.googleapis.com/customsearch/v1"
+ "?q=" + criteria
+ "&cx=005894674626506192190:j1zrf-as6vg"
+ "&key=AIzaSyCanPMUPsyt3mXQd2GOhMZgD4l472jcDNM"
+ "&dateRestrict=" + date_length,
type: 'GET'
}))
);
totalResultsArr.sort();
var countResultsArr = JSON.stringify(totalResultsArr);
var data2 = await $.ajax({
url: 'updateSearchDb.php',
type: 'POST',
async: true,
dataType: 'text',
data: { 'countResultsArr': countResultsArr },
error: function(a, b, c) { alert(a+b+c); }
});
if(data2 == "NORECORD") {
resultsDiv.innerHTML = 'Updated failed. There was a problem with the database';
} else {
resultsDiv.innerHTML = 'Update was successful';
}
}
} catch(e) {
alert('Some unexpected error occured: ' + e);
}
});
UPDATE 2016
Unfortunately the async/await proposal didn't make it to the ES7 specification ultimately, so it is still non-standard.
You could reformat your getTotalResults function in the following matter, it would then search rather sequential, but it should also do the trick in returning your results with an extra callback.
'use strict';
function getTotalResults(searchParam, callback) {
var url = "https://www.googleapis.com/customsearch/v1?q={param}&cx=005894674626506192190:j1zrf-as6vg&key=AIzaSyCanPMUPsyt3mXQd2GOhMZgD4l472jcDNM&dateRestrict=" + (new Date()).getTime(),
i = 0,
len = searchParam.length,
results = [],
req, nextRequest = function() {
console.log('received results for "' + searchParam[i] + '"');
if (++i < len) {
completeRequest(url.replace('{param}', searchParam[i]), results, nextRequest);
} else {
callback(results);
}
};
completeRequest(url.replace('{param}', searchParam[0]), results, nextRequest);
}
function completeRequest(url, resultArr, completedCallback) {
var req = new XMLHttpRequest();
req.open("GET", url, true);
req.onreadystatechange = function() {
if (this.readyState === 4 && this.status == 200) {
var totalResults = JSON.parse(this.responseText).queries.nextPage[0].totalResults;
resultArr.push(totalResults);
completedCallback();
}
};
req.send();
}
getTotalResults(['ford', 'volkswagen', 'citroen', 'renault', 'chrysler', 'dacia'], function(searchResults) {
console.log(searchResults.length + ' results found!', searchResults);
});
However, since you already use JQuery in your code, you could also construct all the requests, and then use the JQuery.when functionality, as explained in this question
Wait until all jQuery Ajax requests are done?
To get the callback execute after google calls are finished you could change:
var requestCounter = 0;
var helperFunc = function(arrayIndex)
{
return function()
{
if (arrXhr[arrayIndex].readyState === 4 && arrXhr[arrayIndex].status == 200)
{
requestCounter++;
totalResults = JSON.parse(arrXhr[arrayIndex].responseText).queries.nextPage[0].totalResults;
totalResultsArr.push(totalResults);
if (requestCounter === search_criterias.length) {
callbackFunction.apply(totalResultsArr);
}
}
}
}
then remove the setTimeout on searchCreteriaFuc.
Consider using promises and Promise.all to get all much cleaner :D

WinJS Virtualized Data Source + nested asynchronous requests

Hi i'm relatively new to JavaScript and i'm working on a winjs app project where i want to use the Bing image search data source example in my project to virtualize the datasource of a listview.
My problem is understanding how the asynchronous functions work together and how to implement an async xhr request within the existing one.
Currently i'm using a synchronous request but i would like to change that into a asynchronous one.
This is my data adapter:
(function () {
var xxxDataAdapter = WinJS.Class.define(
function (devkey, query, delay) {
this._minPageSize = 2;
this._maxPageSize = 5;
this._maxCount = 50;
this._devkey = devkey;
this._query = query;
this._delay = 0;
},
{
getCount: function () {
var that = this;
var requestStr = 'http://xxx/' + that._query;
return WinJS.xhr({ url: requestStr, type: "GET", /*user: "foo", password: that._devkey,*/ }).then(
function (request) {
var obj = JSON.parse(request.responseText);
if (typeof obj.error === "undefined") {
var count = obj.length;
if (count === 0) { console.log("The search returned 0 results.", "sample", "error"); }
return count;
} else {
console.log("Error fetching results from API", "sample", "error");
return 0;
}
},
function (request) {
if (request && request.name === "Canceled") {
return WinJS.Promise.wrapError(request);
} else {
if (request.status === 401) {
console.log(request.statusText, "sample", "error");
} else {
console.log("Error fetching data from the service. " + request.responseText, "sample", "error");
}
return 0;
}
});
},
itemsFromIndex: function (requestIndex, countBefore, countAfter)
{
var that = this;
if (requestIndex >= that._maxCount) {
return WinJS.Promise.wrapError(new WinJS.ErrorFromName(WinJS.UI.FetchError.doesNotExist));
}
var fetchSize, fetchIndex;
if (countBefore > countAfter) {
//Limit the overlap
countAfter = Math.min(countAfter, 0);
//Bound the request size based on the minimum and maximum sizes
var fetchBefore = Math.max(Math.min(countBefore, that._maxPageSize - (countAfter + 1)), that._minPageSize - (countAfter + 1));
fetchSize = fetchBefore + countAfter + 1;
fetchIndex = requestIndex - fetchBefore;
} else {
countBefore = Math.min(countBefore, 10);
var fetchAfter = Math.max(Math.min(countAfter, that._maxPageSize - (countBefore + 1)), that._minPageSize - (countBefore + 1));
fetchSize = countBefore + fetchAfter + 1;
fetchIndex = requestIndex - countBefore;
}
var requestStr = 'http://xxx/' + that._query;
return WinJS.xhr({ url: requestStr, type: "GET", /*user: "foo", password: that._devkey,*/ }).then(
function (request)
{
var results = [], count;
var obj = JSON.parse(request.responseText);
if (typeof obj.error === "undefined")
{
var items = obj;
for (var i = 0, itemsLength = items.length; i < itemsLength; i++)
{
var dataItem = items[i];
var req = new XMLHttpRequest();
// false = synchronous
req.open("get", "http://xxxxx/" + dataItem.id, false);
req.send();
var jobj = JSON.parse(req.response);
if (typeof jobj.error === "undefined")
{
results.push({
key: (fetchIndex + i).toString(),
data: {
title: jobj.name.normal,
date: Date.jsonFormat(dataItem.calculatedAt, "Do, MMM HH:mm Z"),
result: "",
status: "",
}
});
}
}
return {
items: results, // The array of items
offset: requestIndex - fetchIndex, // The offset into the array for the requested item
};
} else {
console.log(request.statusText, "sample", "error");
return WinJS.Promise.wrapError(new WinJS.ErrorFromName(WinJS.UI.FetchError.doesNotExist));
}
},
function (request)
{
if (request.status === 401) {
console.log(request.statusText, "sample", "error");
} else {
console.log("Error fetching data from the service. " + request.responseText, "sample", "error");
}
return WinJS.Promise.wrapError(new WinJS.ErrorFromName(WinJS.UI.FetchError.noResponse));
}
);
}
});
WinJS.Namespace.define("xxx", {
datasource: WinJS.Class.derive(WinJS.UI.VirtualizedDataSource, function (devkey, query, delay) {
this._baseDataSourceConstructor(new xxxDataAdapter(devkey, query, delay));
})
});
})();
And this is the synchronous request i would like to change to an asynchronous one:
var req = new XMLHttpRequest();
// false = synchronous
req.open("get", "http://xxxxx/" + dataItem.id, false);
req.send();
you can use then function to chain promises. In your scenario, then function need to simple have a if statement.
return WinJS.xhr(params).then(function (req)
{
if (..)
return WinJS.xhr(params2);
else
return; // then function ensures wrapping your sync result in a completed promise
}, function onerror(e)
{
// todo - error handling code e.g. showing a message box based on your app requirement
});
This is what i came up with. Map the json objects received asynchronously and make another asynchronous call for each object to get additional data. Then the nested async calls are joined and returned when all are finished.
return WinJS.xhr({ url: 'http://xxx=' + that._query }).then(function (request) {
var results = [];
var obj = JSON.parse(request.responseText);
var xhrs = obj.map(function (dataItem, index) {
return WinJS.xhr({ url: 'http://xxxx' + dataItem.attrx }).then(
function completed(nestedRequest) {
var xxJobj = JSON.parse(nestedRequest.responseText);
var dataObj = {};
dataObj.title = xxJobj.name;
dataObj.date = Date.jsonFormat(dataItem.attrtrxx, "Do, MMM HH:mm Z");
dataObj.result = "open";
dataObj.status = "foo";
if (dataItem.xx.hasOwnProperty("attrx5")) {
dataObj.opponent = dataItem.attrx4;
} else {
dataObj.opponent = dataItem.attrx3;
}
dataObj.page_title = "xXx";
dataObj.match_id = dataItem.id;
dataObj.type = "largeListIconTextItem";
dataObj.bg_image = "http://xxx/" + xxJobj.attrx2 + "-portrait.jpg";
results.push({
key: (fetchIndex + index).toString(),
data: dataObj
});
},
function (err) {
console.log(err.status);
console.log(err.responseText);
}
);
});
return WinJS.Promise.join(xhrs).then(
function (promises) {
return {
items: results, // The array of items
offset: requestIndex - fetchIndex, // The offset into the array for the requested item
};
},
function (err) {
console.log(JSON.stringify(err));
}
);
});

Javascript does user exists, returning value from ajax to late?

I have a script that tells a visitor if the username is already exist or not before he can proceed,
Below you see a part of my code;
EDIT: Ok I have read what you guys said, and modified it, but I still dont get it to work :S, my teacher doesn't know it either...
<script type="text/javascript">
jQuery(document).ready(function(){
// Smart Wizard
jQuery('#wizard').smartWizard({onFinish: onFinishCallback, onLeaveStep: onNextStep});
function onNextStep(){
validateSteps(function (next) { return next; });
}
function onFinishCallback(){
alert('Finish Clicked');
}
function UsernameExist(fullname, callback)
{
    var data = 'user='+ fullname;
    if(fullname) {
        $.ajax({
            type: "POST",
            url: "user_check.php",
            data: data,
async: false,
            beforeSend: function(html) {
                $("#msg_lastname").html('');
            },
            success: function(html){
                $("#msg_lastname").show();
                 $("#msg_lastname").append(html);
if(html.search("red") != -1)
{
callback(false);
}
else
{
callback(true);
}
            }
        });
}
}
function validateSteps(callback){
var isStepValid = true;
// validate step 1
var firstname = $('#firstname').val();
if(!firstname || (firstname.length < 3 || firstname.length > 10))
{
$('#msg_firstname').html('<br/><font color="red">Enter a first name, between 3 and 10 letters.</font>').show();
isStepValid = false;
}
else
{
$('#msg_firstname').html('').hide();
}
var lastname = $('#lastname').val();
if(!lastname || (lastname.length < 3 || lastname.length > 14))
{
$('#msg_lastname').html('<br/><font color="red">Enter a last name, between 3 and 14 letters.</font>').show();
isStepValid = false;
}
else
{
$('#msg_lastname').html('').hide();
}
var gender = $('#gender').val();
if(!gender || Number(gender) == -1)
{
$('#msg_gender').html('<br/><font color="red">Choose your gender!</font>').show();
isStepValid = false;
}
else
{
$('#msg_gender').html('').hide();
}
var age = $('#age').val();
if(!age || Number(age) > 90 || Number(age) < 21)
{
$('#msg_age').html('<br/><font color="red">Enter a age between 21 and 90.</font>').show();
isStepValid = false;
}
else
{
$('#msg_age').html('').hide();
}
var pin = $('#pin').val();
if(!pin || pin.length > 10 || pin.length < 4)
{
$('#msg_pin').html('<br/><font color="red">Enter a PIN between 4 and 10 numbers.</font>').show();
isStepValid = false;
}
else
{
$('#msg_pin').html('').hide();
}
if (isStepValid) {
UsernameExist(firstname + ' ' + lastname, function (exists) {
callback( exists );
});
} else {
callback( false );
}
}
jQuery('select, input:checkbox').uniform();
});
</script>
Now the problem is that when I run this script, it returns undefined, I guess because the UsernameExist is not done fast enough, and it seems the return UsernameExist is not waiting for it for some reason...
You are returning UsernameExists before it has been run.
Instead, call UsernameExists like this:
if (isStepValid) {
UsernameExist(firstname + ' ' + lastname, function (exists) {
return exists;
});
} else {
return false;
}
This works because UsernameExists expects a callback function and on success passes either true or false to callback().
you need just to set async option as false
function UsernameExist(fullname, callback) {
var data = 'user=' + fullname;
if (fullname) {
$.ajax({
type: "POST",
url: "user_check.php",
data: data,
async: false,
beforeSend: function (html) {
$("#msg_lastname").html('');
},
success: function (html) {
//your code after success
}
});
}
}
from jQuery documentation jQuery.ajax
If you need synchronous requests, set this option to false
so you need to execute your ajax call and wait until it's completely finish to execute what you want based on the result
Maybe you should call UsernameExist(fullname, callback) after jQuery load complete.
try this :
getScript('http://code.jquery.com/jquery-1.9.1.min.js', function () {UsernameExist(fullname, callback)});
function getScript(url, callback) {
var script;
script = document.createElement("script");
script.setAttribute('language', 'javascript');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', url);
var done = false;
vObj = script.onload;
script.onload = script.onreadystatechange = function () {
if (!done && (!this.readyState ||
this.readyState == "loaded" || this.readyState == "complete")) {
done = true;
if (typeof callback === 'function')
callback(this.ownerDocument.attributes);
}
};
var head = document.getElementsByTagName('head')[0];
head.appendChild(script);}
Try something like this :
// Smart Wizard
$('#wizard').smartWizard({onFinish: onFinishCallback, onLeaveStep: onNextStep});
function onNextStep() {
var isValid = validateSteps();
alert(isValid);
}
function onFinishCallback(){
alert('Finish Clicked');
}
function UsernameExist(fullname)
{
var data = 'user='+ fullname;
var userAlreadyExists = null;
if(fullname) {
$.ajax({
type: "POST",
url: "user_check.php",
data: data,
async: false,
beforeSend: function(html) {
$("#msg_lastname").html('');
},
success: function(html){
$("#msg_lastname").show();
$("#msg_lastname").append(html);
if(html.search("red") != -1)
{
userAlreadyExists = false;
}
else
{
userAlreadyExists = true;
}
}
});
}
return userAlreadyExists;
}
function validateSteps(){
...
if (isStepValid) {
return UsernameExist(firstname + ' ' + lastname);
} else {
return false;
}
}

Categories