javascript callback function call itself until true - javascript

I am running a function that i need to keep running until i get a response example
exports.getJson = function(url, callback) {
var loader = Titanium.Network.createHTTPClient();
loader.open("GET", url);
loader.onload = function() {
var response = JSON.parse(this.responseText);
callback(response);
};
loader.onerror = function(e) {
callback(false);
};
// Send the HTTP request
loader.send();
}
ok the problem i am having is it will sometimes give me a response of null and i need it to run again.
so i am calling it like this.
url = 'http://example.com/test.json';
main.getJson(url, function(response) {
if(response){
addData(response);
}else{
//return no response i need to run the function again now until it comes back as true
}
});
Can anyone give me a good way to do this maybe try at least 3 times then return false???
Thanks

Just put the code in function and call it again:
var counter = 0;
function getData() {
main.getJson('http://example.com/test.json', function(response) {
if(response){
addData(response);
}
else if (counter < 3) {
counter++;
getData();
}
});
});

Related

JavaScript not getting function returns in Node.js

I have made an IRC bot for purely learning purposes but I have a Minecraft server that I use an API to get the status back as JSON. Now I have made the code and it works but for some reason when I try and use a return on the function so I can get the content it seems to not work?
So I have the two functions below:
function getservers(name) {
if (name == "proxy") {
var Request = unirest.get(proxy);
Request.header('Accept', 'application/json').end(function (response) {
main = response["raw_body"];
data = JSON.parse(main);
console.log(data["motd"]);
return data.motd;
});
} else if (name == "creative") {
var Request = unirest.get(creative);
Request.header('Accept', 'application/json').end(function (response) {
main = response["raw_body"];
data = JSON.parse(main);
return data;
});
} else if (name == "survival") {
var Request = unirest.get(survival);
Request.header('Accept', 'application/json').end(function (response) {
main = response["raw_body"];
data = JSON.parse(main);
return data;
});
}
}
// Main logic:
function parsemessage(msg, to) {
// Execute files
function pu(o,t,f){if(o)throw o;if(f)throw f;bot.say(to,t)}
if (msg.substring(0,1) == pre) {
// Get array
msgs = msg.split(' ');
console.log(msgs[0]);
// Run Login
if (msgs[0] == pre+"help") {
bot.say(to, "Help & Commands can be found here: https://server.dannysmc.com/bots.html");
} else if (msgs[0] == pre+"status") {
// Get status of server, should return online/offline - player count for each server - motd
server = getservers("proxy");
console.log(server);
/*var data = '';
var Request = unirest.get('https://mcapi.us/server/status?ip=185.38.149.35&port=25578');
Request.header('Accept', 'application/json').end(function (response) {
main = response["raw_body"];
data = JSON.parse(main);
});
} else if (msgs[0] == pre+"players") {
// Should return the player list for each server
} else if (msgs[0] == pre+"motd") {
// Should return the message of the day.
} else if (msgs[0] == pre+"ip") {
bot.say(to, "ShinexusUK IP Address: shinexusuk.nitrous.it");
} else if (msgs[0] == pre+"rules") {
}
}
}
The code in the getservers() function works, when I do the
console.log(data["motd"]);
It outputs my servers message of the day. But when I do return
data.motd
(same as data["motd"]?) The code that calls the function is here
server = getservers("proxy");
console.log(server);
Please note this is a node.js code and it contains many files so i can't exactly paste it. So here is the link to the github repo with the whole node application: Here
When the function getservers is called, it makes an asynchronous request and return nothing.
Then the callback is fired with the response of that request as parameter.
Note that the function getservers will end before the end callback of your request is called
(simplified version)
function getservers(name) {
var Request = unirest.get(proxy);
Request.header('Accept', 'application/json').end(function (response) {
main = response["raw_body"];
data = JSON.parse(main);
console.log(data["motd"]);
return data.motd;
});
// nothing returned here
}
What you need is a function callback that will be called after you got the response.
function getservers(name, callback) { // callback added
var Request = unirest.get(proxy);
Request.header('Accept', 'application/json').end(function (response) {
main = response["raw_body"];
data = JSON.parse(main);
console.log(data["motd"]);
callback(data.motd); // fire the callback with the data as parameter
});
// nothing returned here
}
And then you can use your function like this :
getservers("proxy", function(server){
console.log(server);
....
})

How do I wait for a .each loop that makes async calls?

I have some javascript code that updates some data to a database using a http handler, but this async call is made inside an .each loop. At the end of the loop I make a call to function CancelChanges() that refreshed the page. The problem is that the page seems to refresh before the database is updated. The .each loop seems to finish after the call to CancelChanges(). How can I make sure the page is refreshed after all the async calls are completed in the .each loop?
function SaveChanges() {
if (PreSaveValidation()) {
var allChangesSucceeded = true;
var studioId = $("#param_studio_id").val();
var baseDate = $("#param_selected_month").val().substring(6, 10) + $("#param_selected_month").val().substring(0,2);
var currency = "CAD";
var vacationPct = null;
var gvAdmissible = null;
$(".editable-unsaved").each( function() {
var newSalary = $(this).text();
var disciplineId = $(this).data("disciplineid");
var seniorityId = $(this).data("seniorityid");
var handlerCommand = "";
if ($(this).data("valuetype") === "inflated") {
handlerCommand = "AddAverageSalary";
} else if ($(this).data("valuetype") === "actual") {
handlerCommand = "UpdateAverageSalary";
}
$.get("WS/AverageSalary.ashx", { command: handlerCommand, studio_id: studioId, discipline_id: disciplineId, seniority_id: seniorityId, base_date: baseDate, currency: currency, salary: newSalary, vacation_pct: vacationPct, gv_admissible: gvAdmissible }).done(function (data) {
if (data != "1") {
$(this).removeClass("editable-unsaved");
allChangesSucceeded = true;
}
else {
alert('fail');
allChangesSucceeded = false;
}
});
});
if(allChangesSucceeded) CancelChanges();
}
}
function CancelChanges() {
var href = window.location.href;
href = href.split('#')[0];
window.location.href = href;
}
You could try using Promises and jQuery $.when
Store a list of the ajax call promises:
var defereds = [];
$(".editable-unsaved").each( function() {
//...
defereds.push($.get("WS/AverageSalary.ashx" /*...*/));
}
$.when.apply($, defereds).done(function() {
CancelChanges();
});
This should, hopefully, wait for all the ajax calls to finish before calling CancelChanges()
I think you need to change your structure a little bit, using a counter and calling CancelChanges when the counter equals the number of calls.
function SaveChanges() {
if (PreSaveValidation()) {
var studioId = $("#param_studio_id").val();
var baseDate = $("#param_selected_month").val().substring(6, 10) + $("#param_selected_month").val().substring(0,2);
var currency = "CAD";
var vacationPct = null;
var gvAdmissible = null;
var editableUnsaveds = $(".editable-unsaved"); //cache the selector here, because selectors are costly
var numOfGetsReturned = 0;
editableUnsaveds.each( function() {
var newSalary = $(this).text();
var disciplineId = $(this).data("disciplineid");
var seniorityId = $(this).data("seniorityid");
var handlerCommand = "";
if ($(this).data("valuetype") === "inflated") {
handlerCommand = "AddAverageSalary";
} else if ($(this).data("valuetype") === "actual") {
handlerCommand = "UpdateAverageSalary";
}
$.get("WS/AverageSalary.ashx", { command: handlerCommand, studio_id: studioId, discipline_id: disciplineId, seniority_id: seniorityId, base_date: baseDate, currency: currency, salary: newSalary, vacation_pct: vacationPct, gv_admissible: gvAdmissible }).done(function (data) {
if (data != "1") {
$(this).removeClass("editable-unsaved");
}
else {
alert('fail');
}
if(editableUnsaveds.length === ++numOfGetsReturned){
CancelChanges(); //now it should call when the final get call finishes.
}
});
});
}
}
function CancelChanges() {
var href = window.location.href;
href = href.split('#')[0];
window.location.href = href;
}
I'd use promises. The q library is my favorite way to implement them. But since you're using JQuery, I'd recommend following a similar approach to what I outline below, but using $.when, instead of q.allSettled
I often use promises when scraping tons of websites at once -- I need to iterate through a long list of websites, make requests for content, and do something with the content when the requests return. The last thing I want to do is send requests one at a time, handling each one as it returns.
In the abstract, that looks something like this:
function scrapeFromMany() {
var promises = [];
_.forEach(urls, function(url) {
// this makes the request
var promise = scraper(url);
// this stores the promise with the others you iterate through
promises.push(promise);
});
q.allSettled(promises).then(function(res) {
// this function is executed when all of the promises (requests) have been resolved
console.log("Everything is done -- do something with the results.", res);
});
}
Fwiw, promises aren't that easy to grok if you've never used them. If that's the case, plan on spending some time getting up to speed with the concepts. They'll change (for the much much better) the way you write async javascript, and they really are the blessed path with these sorts of operations.
Asynchronously call your check function within the "done" function handler. Keep track of how many requests have completed, and only do your processing once that's equal to the total number of expected requests.
if (PreSaveValidation()) {
var allChangesSucceeded = true;
var length = $(".editable-unsaved").length;
var completedCount = 0;
// ...
$(".editable-unsaved").each( function() {
// ...
$.get("WS/AverageSalary.ashx", data).done(function (data) {
completedCount++;
if (data != "1") {
$(this).removeClass("editable-unsaved");
// don't set all changes succeeded to true here
}
else {
alert('fail');
allChangesSucceeded = false;
}
isComplete(length, completedCount, allChangesSucceeded);
});
});
}
function isComplete(totalLength, currentLength, allChangesSucceeded) {
if (currentLength == totalLength) {
// should this be !allChangesSucceeded?
if (allChangesSucceeded) CancelChanges();
}
}
This happens because you are not waiting for the requests to complete to proceed with the loop.
To achieve so you have to set the "async" flag to false.
The call to the server should be like this:
$.ajax({
url: "WS/AverageSalary.ashx",
async: false,
data:{ command: handlerCommand, studio_id: studioId, discipline_id: disciplineId, seniority_id: seniorityId, base_date: baseDate, currency: currency, salary: newSalary, vacation_pct: vacationPct, gv_admissible: gvAdmissible },
success: function (data) {
if (data != "1") {
$(this).removeClass("editable-unsaved");
allChangesSucceeded = true;
}
else {
alert('fail');
allChangesSucceeded = false;
}
}
});

Waiting for two asynchonous requests

I'm having trouble sending two request in PHP and waiting for both answers. Here is my code :
function getXDomainRequest() {
var xdr = null;
if (window.XDomainRequest) {
xdr = new XDomainRequest();
} else if (window.XMLHttpRequest) {
xdr = new XMLHttpRequest({mozSystem: true});
} else {
alert("Your browser does not support AJAX");
}
return xdr;
}
function sendData() {
var json1= "";
var json2= "";
var xdr = getXDomainRequest();
xdr.onload = function() {
json1 = xdr.responseText;
}
var xdr2 = getXDomainRequest();
xdr2.onload = function() {
json2 = xdr2.responseText;
}
var Id = document.querySelector('#searchField').value;
// Call API
xdr.open("GET", "./dorequest.php?id=" + Id + "&requesttype=player");
xdr.send();
xdr2.open("GET", "./dorequest.php?id=" + Id + "&requesttype=stats");
xdr2.send();
xdr.wait();
// Display results
getHtmlResults(jsonPlayer, jsonStats);
}
As expected here the json1 and json2 are still empty when getHtmlResults is called. I could do it synchronously by calling the xdr2.send() into the xdr.onload and my final function in the xdr2.onload but I want to do it asynchronously to get a better response time.
Thanks !
(any other comment on the code is welcome I'm quite new to php :) )
EDIT :
So I tryied using Ajax and it seems to work :)
var jsonPlayer = "";
var jsonStats = "";
var steamId = document.querySelector('#searchField').value;
$.when(
$.ajax({url: "./dorequest.php?steamid=" + steamId + "&requesttype=playersummary",
success: function(response){ jsonPlayer = response; }}),
$.ajax({url: "./dorequest.php?steamid=" + steamId + "&requesttype=csgostats",
success: function(response){ jsonStats = response; }}) ).done(
function(player, stats) {
getHtmlResults(player, stats);
});
Promises are commonly used as an abstraction to deal with asynchronous processes.
Wrap your AJAX calls in a Promise to do:
var ajax1 = request("stats");
var ajax2 = request("player");
when(ajax1, ajax2).done(function (stats, player) {
console.log(stats, player);
});
Most popular frameworks have a built-in Promise API.
You can send both the calls ASync and have a function in both .onload which checks if the other request has completed. So as soon as one of the onload finds that the other onload is done, you can call the getHtmlResults function.

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;
}
}
}

Categories