Function with AJAX run last, how to make it run first - javascript

I have one function with AJAX Call(Below Code):
function get_type(Name) {
var field_name;
$.ajax({
type: "GET",
url: "../home/Asset/MR/MR.xml",
dataType: "xml",
success: function(xml) {
$(xml).find('pub').each(function() {
if (Name == $(this).find('pro').text()) {
$(this).find('metadata field').each(function() {
field_name = $(this).find('name').text();
if (field_name == "little") {
type = "L";
} else if (field_name == "Big") {
type = "b";
}
});
}
});
}
});
}
This code works well but the problem is it run after all the functions finished. I want to run this code first I need to get data from the XML. I need to stop the loop of $(xml).find('pub').each(function() this once the Name== $(this).find('pro').text() text is matched. Because this loop execute even I get the answers.
Calling Function codes:
var rd = new FileReader();
rd.onload = function(e) {
var xmlDoc = $.parseXML(this.result);
var $xml = $(xmlDoc);
var J_Name = $xml.find('meta').text();
get_type(J_Name);
//check allowed child of front tag
check_allowed_direct_child("places", "Tirunelveli,Tiruchendur,Alwar", "RULE_002", "Fail");
};
rd.readAsText(this.files[i]);

Callbacks to the rescue!
function get_type(name, cb) {
cb = cb || function () {};
var field_name;
var type;
var types_map = {
'little': 'L',
'Big': 'b'
};
$.ajax({
type: 'GET',
url: '../home/Asset/MR/MR.xml',
dataType: 'xml',
success: function (xml) {
$(xml)
.find('pub')
.each(function () {
if (name == $(this).find('pro').text()) {
$(this)
.find('metadata field')
.each(function () {
field_name = $(this)
.find('name')
.text();
if (types_map.hasOwnProperty(field_name)) {
type = types_map[field_name];
return false; // break out of each()
}
});
return false; // break out of each()
}
});
cb(type); // execute provided callback
}
});
}
var rd = new FileReader();
rd.onload = function (e) {
var xmlDoc = $.parseXML(this.result);
var $xml = $(xmlDoc);
var J_Name = $xml.find('meta').text();
get_type(J_Name, function (type) {
// do stuff once get_type() resolves, type being either matched type or undefined
check_allowed_direct_child('places', 'Tirunelveli,Tiruchendur,Alwar', 'RULE_002', 'Fail');
});
};
rd.readAsText(this.files[i]);
If interested, read on how to make use of Promises, to make callback code a lot more digest: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
If still interested, read on how to use async / await to make Promises code a lot more digest: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

Related

Fill array by multiple AJAX requests, then pass array to another function

(My solution below)
I have several HTML elements with class .canvas-background of which information is stored in the database. I want to get the information of each element and process it via JavaScript. But somehow I can't pass the response of the AJAX request to another function. Here is what I've tried:
function initTabs() {
var tabs = loadTabInformation();
console.log(tabs); // (1)
// do something else
}
function loadTabInformation() {
var requests = new Array();
var tabs = new Object();
var counter = 0;
$(".canvas-background").each(function () {
var tabNumber = $(this).data("tab-number");
var request = $.ajax({
type: 'POST',
url: '../db/GetTabInformation.ashx',
data: String(tabNumber),
dataType: 'json',
contentType: 'text/plain; charset-utf-8'
})
.done(function (response) {
tabs[counter++] = response;
}).fail(function (jqXHR, textStatus, errorThrown) {
console.log("request error in loadTabInformation()");
console.log(textStatus);
console.log(errorThrown);
});
requests.push(request);
});
$.when.apply($, requests).done(function () {
console.log(tabs); // (2)
return tabs;
});
}
At (1) I get undefined, but at (2) everything seems to be alright.
THE SOLUTION:
Thanks to the answer and the link in the comment #Kim Hoang provided I got this working. The clue seemed to put the done() function in the calling function, that is initTabs() in my case. Another thing I got wrong was to try to do the logic that should be executed after the AJAX requests had finished outside the done callback function. They must be inside (makes sense, if you think about it). And a lot of conosle output helped, to see what function returns what kind of object.
function initTabs() {
var tabInfoRequest = loadTabInfo();
tabInfoRequest[0].done(function() {
var results = (tabInfoRequest[1].length > 1) ? $.map(arguments, function(a) { return a[0]; }) : [arguments[0]];
for (var i = 0; i < results.length; i++) {
// do something with results[i]
}
});
}
function loadTabInfo() {
var tabNumbers = new Array();
$(".canvas-background").each(function () {
tabNumbers.push($(this).data("tab-number"));
});
var requests = $.map(tabNumbers, function (current) {
return $.ajax({
type: 'POST',
url: '../db/GetTabInformation.ashx',
data: String(current),
dataType: 'json',
contentType: 'text/plain; charset-utf-8'
});
});
var resultObject = new Object();
resultObject[0] = $.when.apply($, requests);
resultObject[1] = requests;
return resultObject;
}
Note: I only did the resultObject-thing because I needed the array requests in the initTabs() function.
Thank you very much for helping me!
You do not return anything in loadTabInformation, so of course you will get undefined. You should do it like this:
function loadTabInformation() {
...
return $.when.apply($, requests);
}
function initTabs() {
loadTabInformation().done(function (tabs) {
console.log(tabs); // (1)
// do something else
});
}

How to make remote jquery validation for tied fields?

Let's say I have couple of input fields - their combination must be unique.
Each of them causes remote validation method triggering - and it's the same method for both fields. If combination is unique - it returns true.
The problem is following: when after validation error I change the field, that is not marked as erroneous, the erroneous field keeps being considered erroneous, even if method returns true (the couple is unique)!
I even don't need to make extra request to server, because the couple is unique! I just need to clear error for field, marked erroneous. However, I have not managed to do this - seems like jquery does not offer functionality for this.
Any ideas?
The relevant code is pretty huge, but the key parts are here:
this.clearErrors = function ($elements) {
var $validator = $elements.first().closest('form').validate();
$elements.each(function(index, item) {
var $parent = $(item).parent();
var element = $(item).get(0);
if ($parent.is('td')) {
$parent.removeClass(window.resources.errorCellClass);
}
$parent.find('span.' + window.resources.errorSpanClass).remove();
$validator.successList.push(element);
delete $validator.invalid[element.name];
delete $validator.submitted[element.name];
});
};
//Fixing remote method, since original one returned "pending" status all the time, as reported in other stackoverflow question
$.validator.addMethod('synchronousRemote', function (value, element, param) {
if (this.optional(element)) {
return 'dependency-mismatch';
}
var previous = this.previousValue(element);
if (!this.settings.messages[element.name]) {
this.settings.messages[element.name] = {};
}
previous.originalMessage = this.settings.messages[element.name].remote;
this.settings.messages[element.name].remote = previous.message;
if (typeof param == 'string') {
param = { url: param }
}
if (previous.old === value) {
return previous.valid;
}
previous.old = value;
var validator = this;
this.startRequest(element);
var data = {};
data[element.name] = value;
var valid = 'pending';
$.ajax($.extend(true, {
url: param,
async: false,
mode: 'abort',
port: 'validate' + element.name,
dataType: 'json',
data: data,
success: function (response) {
validator.settings.messages[element.name].remote = previous.originalMessage;
valid = response === true || response === 'true';
if (valid) {
var submitted = validator.formSubmitted;
validator.prepareElement(element);
validator.formSubmitted = submitted;
validator.successList.push(element);
delete validator.invalid[element.name];
validator.showErrors();
} else {
var errors = {};
var message = response || validator.defaultMessage(element, 'remote');
errors[element.name] = previous.message = $.isFunction(message) ? message(value) : message;
validator.invalid[element.name] = true;
validator.showErrors(errors);
}
previous.valid = valid;
validator.stopRequest(element, valid);
}
}, param));
return valid;
});
$root.filter(':input[data-excluded-values-method]:not([readonly])').add($root.find(':input[data-excluded-values-method]:not([readonly])')).each(function () {
var $element = $(this);
$element.validate({
onkeyup: false
})
var $entityContainer = $element.closest('[data-entity]');
var $keyFields = $entityContainer.filter('INPUT[data-is-key]:not([disabled])').add($entityContainer.find('INPUT[data-is-key]:not([disabled])'));
var localizedNames = [];
$keyFields.each(function () {
localizedNames.push($(this).attr('localized-name'));
});
$element.rules('add',
{
synchronousRemote: function () {
var key = [];
var keyIsUnique = true;
$keyFields.each(function () {
key.push($(this).val());
});
return {
url: $element.attr('data-excluded-values-method'),
type: 'POST',
async: false,
data: JSON.stringify({
key: key,
entityType: $entityContainer.attr('data-entity')
}),
contentType: 'application/json; charset=utf-8',
dataType: 'json',
dataFilter: function (isUnique) {
keyIsUnique = isUnique;
return isUnique;
},
complete: function () {
if (keyIsUnique === 'true') {
window.commonUtils.clearErrors($keyFields.filter('[name!="' + $element.attr('name') + '"]:input[data-excluded-values-method]:not([readonly])'));
}
}
}
},
messages: {
synchronousRemote: $.validator.format(window.resources.notUniqueValidationError)(localizedNames.join(' + '))
}
});
});
I've debugged jquery validate method and found what yet should be set to clear validation error:
$validator.previousValue(element).valid = true;
Now everything works.

Use Parse Query in then() when using Cloud Code

I can’t seem to get this simple Parse query to work in my cloud code then() it works outside of this but when i place the code inside of this then function nothing happens. The variables are just placeholders for now in terms of testing but i have the default TestObject class you get when you start Parse from the beginning but for some reason it just keeps on returning nothing.
Here is the full function that i am currently using.
// Function which will get the data from all the links passed into the function
Parse.Cloud.define("myNews", function (request, response) {
var promises = _.map(import_io_keys, function (news_api_key) {
return Parse.Cloud.httpRequest({
method: 'GET',
url: "https://api.import.io/store/connector/" + news_api_key + "/_query?input=webpage/url:https%3A%2F%2Fwww.designernews.co%2Fnew&&_apikey=xxxxxxxxxxxxxxxxxx",
headers: {
'Content-Type': 'application/json;charset=utf-8'
}
}).then(function (httpResponse) {
result = JSON.parse(httpResponse.text);
var success = false;
var news_icon = "";
var news_source_name = "";
var query = new Parse.Query("TestObject");
query.find({
success: function(results) {
success = true;
news_icon = results[0].get("foo");
news_source_name = results[0].get("foo");
response.success("done" + news_icon);
},
error: function() {
success = false;
response.error("Query lookup failed");
}
});
for (var story in result.results) {
if(story.length > 0){
if (story["article_link/_text"] !== "" && story["article_link"] !== "" && story["article_time"] !== "") {
if(success){
// Do the stuff later
}
}
}
}
});
});
Parse.Promise.when(promises).then(function () {
console.log("Got all the stories");
response.success(newsJsonData);
}, function () {
response.error("No stories");
console.log("API KEY IS: " + request.params.keys);
});
});

return ajax.done data gives error on jquery

I have data in my ajax.done and it bugs on jquery.
i googled on it and cant find anything.
what to do?
function select_aragement(arragament){
var arrst = arragament;
var arrsplit = arrst.split("|");
var periode = arrsplit[0];
var id = arrsplit[1];
var postsjson;
var test= $.ajax({
type: 'POST',
async: true,
url: 'ajax/prijzen.php',
data: { id: id, periode: periode },
dataType: 'json'
}).done(function (vis) {
console.log(vis);
postsjson = $.parseJSON(vis);
});
return postsjson;
}
You shouldn't be attempting to return anything from a callback function because the returned value doesn't go anywhere meaningful. Instead you simply use the response from the AJAX request inside that callback function.
Let's say you have this code:
function bar() {
var myObject = foo();
// do something with myObject
}
function foo() {
var bar; // 1
var xhr = $.ajax({
url: yourUrl,
dataType: 'json',
type: 'post',
data: {
some: 'data'
}
}); // 2
xhr.done(function(yourObject) {
bar = yourObject; // 5
}); // 3
return bar; // 4
}
bar();
The comments inside the foo function indicate the order in which those statements execute. So you declare a variable bar, declare a variable xhr that has a Deferred object, attach a done handler to it with a callback function, return the value of bar, then the value of bar is set (too late - you've already tried to return it).
Inside of your execution of the bar function myObject is going to be undefined, because the value of bar inside the foo function wasn't set before the return statement. What you need to do is simply move the // do something with myObject code to the callback function, and use bar there:
function foo() {
var xhr = $.ajax({
url: yourUrl,
dataType: 'json',
type: 'post',
data: {
some: 'data'
}
}); // 1
xhr.done(function(yourObject) {
var bar = yourObject; // 4
// do something with bar
}); // 2
// 3 - function execution has finished
}
You might want to move the return line inside the done section
}).done(function (vis) {
console.log(vis);
postsjson = $.parseJSON(vis);
return postsjson;
});
but keep in mind that, being an asynchonous call, so will be your return. My advise would be to pass in a callback.
function select_aragement(arragament, callback){
var arrst = arragament;
var arrsplit = arrst.split("|");
var periode = arrsplit[0];
var id = arrsplit[1];
var postsjson;
var test= $.ajax({
type: 'POST',
async: true,
url: 'ajax/prijzen.php',
data: { id: id, periode: periode },
dataType: 'json'
});
test.done(function (vis) {
console.log(vis);
postsjson = $.parseJSON(vis);
callback && callback(postjson);
});
}
And modify your code to use the callback instead of the returned value.
before
var postjson=select_aragement(arragament);
...stuff with postjson...
after
select_aragement(arragament, function(postjson) {
...stuff with postjson...
});
You are trying to make the ajax call fire synchronously, for that you need to make the async property false.
async: false,
The problem :
Look at the following code :
function getValue(){
var value = 0;
setTimeout(function(){
value = 42;
}, 1000);
return value;
}
What is the returned value ?
fiddle
This is your exact same problem with
function select_aragement(arragament){
var postjson;
$.ajax(...).done(function(vis){
postjson = vis;
});
return postjson;
}
A solution :
I imagine you use your function in the following way :
var data = select_aragement(arragament);
// do something with data :
$.each(data, function(){
....
});
You can change select_aragement's code like this :
function select_aragement(arragament){
var arrst = arragament;
var arrsplit = arrst.split("|");
var periode = arrsplit[0];
var id = arrsplit[1];
var test = $.ajax({
type: 'POST',
async: true,
url: 'ajax/prijzen.php',
data: { id: id, periode: periode },
dataType: 'json'
});
// return the promise which wraps the ajax call
return test;
}
and the calling code like this :
// "p" stands for "promise"
var p = function select_aragement(arragament);
p.done(function(data){
// do something with data :
$.each(data, function(){
....
});
});
or without the local variable :
select_aragement(arragament).done(function(data){
// do something with data :
$.each(data, function(){
....
});
});
In this case you can use async/await mixed to .done from jQuery like this:
async function myasyncfunction(myArgs){
var response = [];
var req = $.ajax({
method: "GET",
url: resquestURL,
dataType: "json",
})
await req.done( res => {
//DO some stuff with your data
for (let index = 0; index < res.length; index++) {
const element = res[index];
response .push( "some stuff" + element );
}
})
return response;
}

Pass a variable to a function from another function in JavaScript (winJs)

Hi I'am working with Windows 8 app using Java Script
function fetchFromLiveProvider(currentList, globalList,value) {
feedburnerUrl = currentList.url,
feedUrl = "http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&output=json&num=999&q=" + encodeURIComponent(feedburnerUrl);
WinJS.xhr({url: feedUrl, responseType: "rss/json"
}).done(function complete(result) {
var jsonData = JSON.parse(result.response);
//console.log(JSON.stringify(jsonData));
var entries = jsonData.responseData.feed;
});
}
function setOther(entries){
//some code here
}
I want to do is pass the entries in the fetchFromLiveProvider function to another function called setOther(entries){}. Thank you for any help...
Since WinJS.xhr returns a promise, you can do the following:
var entriesPromise = function fetchFromLiveProvider(currentList, globalList, value) {
feedburnerUrl = currentList.url,
feedUrl = "http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&output=json&num=999&q=" + encodeURIComponent(feedburnerUrl);
return WinJS.xhr({
url: feedUrl,
responseType: "rss/json"
});
}
function setOther(entries) {
entries.done(function complete(result) {
var jsonData = JSON.parse(result.response);
//console.log(JSON.stringify(jsonData));
var entries = jsonData.responseData.feed;
//some code here
})
}
setOther(entriesPromise);

Categories

Resources