Open weather ajax - ajax

I'm trying to do a ajax call to Openweathermap API and my variables are not being updated once the function leaves ajax. Can someone please explain to me why my var tmp is not being updated.
var url1 = "http://api.openweathermap.org/data/2.5/find?lat=" + marker.position.lat()+"&lon="+marker.position.lng() + "&type=accurate&units=imperial&mode=json&APPID=8cbc2d4c3edf26435cf160f3cee969ed";
var tmp;
$.ajax({
type: 'get',
dataType: "jsonp",
url: url1,
async: false,
success:function (data) {
tmp =data.list[0].main.temp +"F " + data.list[0].weather[0].description;
console.log(tmp); //it logs correctly here
}
});
console.log(tmp); //it says it's undefined here

Ajax is async, not synchronous
your first TMP within the ajax callback will wait for the ajax to complete before execution.
your second TMP outside of your ajax callback will execute straight away before waiting the ajax to complete
You can read up on
https://rowanmanning.com/posts/javascript-for-beginners-async/
some of the js solutions
callbacks ( beginner1 )
Async.js ( beginner2 )
Promises ( intermediate )
ES6 async/await ( advance )

Related

$.ajax in a for loop pulling from a php file

I have a key_gen.php file that contains a function to generate a random key. When executed, the php file gives back one key (tested and it works).
In my javascript file I have a click event on a button (that works), something like this:
$('#kg_btn').click(function(){});
Then, inside my click event I have a functions:
var get_key = function(){
for(var i = 0; i < kg_quantity; i++) {
$.ajax ({
url: "../keygen/gen_rkey.php",
type: "GET",
datatype: "json",
success: function(data) {
var j_obj = JSON.parse(data);
//alert("Success!");
prs = j_obj.test;
console.log(prs);
//add_key();
},
error: function(error) {
alert("Error! Can't send the data");
}
}); //ajax call ends
}
}
When I run this function once (by setting up the "Kg_quantity" variable to 1), every time I click my button I get a correct behavior. The result is a different key on the console.log per click.
If I set up the "kg_quantity" to any other number than 1 (for example: 3,9,10), I do get the console.log messages back, but the number generated is the same.
I was hoping that by inserting the ajax object into a for-loop would execute the ajax call several times. I tried to put the ajax call within a prototype function, as well, but I get the same result.
Edit: I tried adding a closure (as Ross suggested), but I get the exact same result.
Thanks.
AJAX is asynchronous. Your loop will finish before the first AJAX response most likely.
I would restructure that so the success response from the AJAX call will trigger the next iteration. Or if you're lazy you can just set async:false:
$.ajax ({
url: "../keygen/gen_rkey.php",
type: "GET",
async: false,
....
Or even better, put the strain on the server and reduce the back-and-forth so you get all your keys in one response:
url: "../keygen/gen_rkey.php?qty=" + kg_quantity,
UPDATE: Async design method:
function getKeys(max,cur) {
cur = cur || 1;
if (cur == max) {
return;
}
$.ajax({
....
success(function(data) {
// do stuff....
// recursive iteration
getKeys(max,cur + 1);
}
});
}
getKeys(5);

Chain multiple POST requests together using AJAX and jQuery

I received a suggestion from a prior question that I need to amend my code chain a series of POST requests together, but I don't have any idea how to accomplish this. Specifically, the advice I was given was to:
fire off a post, have its success handler fire off the next post,
etc... and then when all the posts are done, the final post's success
handler fires off the get
This strategy makes sense to me but I do not know how to implement. I am trying to prevent the call to GET before all of the calls to POST have completed. Currently, I have implemented $.when.apply to delay the sending of GET. Here is the code for that:
function(){
$.when.apply(undefined, InsertTheAPPs()).done(function () {
$.ajax({
url: sURL + "fileappeal/send_apps_email",
success: function() {
var m = $.msg("my message",
{header:'my header', live:10000});
setTimeout(function(){
if(m)m.setBody('...my other message.');
},3000);
setTimeout(function(){
if(m)m.close(function(){
window.location.replace(sURL+'client/view');
});
},6000);
$('#ajaxShield').fadeOut(1000);},
error: function(){
$.msg("error message",
{header:'error header', live:10000});
}
});
});
}
Here is the code for the jQuery $.each loop. This is the code that needs to not only begin, but must end before the ajax call to fileappeal/send_apps_email above:
function InsertTheAPPs(){
$('input[name=c_maybe].c_box').each(function(){
var jqxhrs = [];
if($(this).prop('checked')){
var rn = $(this).prop('value');
jqxhrs.push(
$.ajax({
url: sURL + 'fileappeal/insert_app',
type:"POST",
dataType: 'text',
data: {'rn': rn},
error: function(data) {console.log('Error:'+rn+'_'+data);}
})
)
return jqxhrs;
}
});
}
Could someone demonstrate how I can modify the code above to implement the strategy of chaining together the multiple POST calls?
Don't return from .each. It doesn't work that way. Instead do this:
var jqxhrs = [];
$(...).each(...
});
return jqxhrs;
Nothing is assigned to the return value of .each, which you can't get anyway. Returning from each allows it to be used like break/continue, which doesn't make sense in your context.
Moreover, the var jqxhrs inside of the each loop causes a new variable to be declared in that context on each iteration of the loop.

Multiple AJAX calls on page load

I'm attempting to pull two separate things from outside sources to put onto an HTML page I'm creating. I have a successful AJAX function to pull the most recent video from a particular Youtube channel by parsing through the XML/RSS feed for that channel. I receive this feed through an AJAX call.
I'd also like to get the most recent blog post from a Blogger account. The code for parsing the feed to get the most recent entry shouldn't be difficult, but I'm having trouble with simultaneous AJAX calls. I read somewhere that it can only handle one at a time? I'm weary about queuing them because I don't want to the content on the page to load in steps. I'd rather it all just get fetched simultaneously. How might I go about doing this?
Here is my current script:
<script type="text/javascript" charset="utf-8">
$(function() {
$.ajax({
type: "GET",
url: "http://gdata.youtube.com/feeds/base/users/devinsupertramp/uploads?orderby=updated&alt=rss&client=ytapi-youtube-rss-redirect&v=2",
dataType: "xml",
success: parseXml
});
});
function parseXml(xml) {
$(xml).find("item:first").each(
function() {
var tmp = $(this).find("link:first").text();
tmp = tmp.replace("http://www.youtube.com/watch?v=", "");
tmp = tmp.replace("&feature=youtube_gdata", "");
var tmp2 = "http://www.youtube.com/embed/" + tmp + "?autoplay=1&controls=0&rel=0&showinfo=0&autohide=1";
var iframe = $("#ytplayer");
$(iframe).attr('src', tmp2);
}
);
}
</script>
I read somewhere that it can only handle one at a time?
Either you misunderstood what the person was trying to say or they were incorrect. Javascript doesn't run any functions concurrently so someone with poor English might reword that as "can only handle one at a time" but that doesn't mean you can't make multiple AJAX calls. jQuery is smart and will do what it needs to do to make sure both calls are executed eventually.
If you'd like all the content to be loaded simultaneously the sad fact is you can't. However you can make it appear that way to the user by declaring a flag that is set by the success method of each call. Then just keep the content hidden until both flags have been set.
EDIT:
Here's a very simplistic approach to make it appear that they are fetched simultaneously:
<script type="text/javascript" charset="utf-8">
var youtubComplete = false;
var otherComplete = false;
$(function() {
$.ajax({
type: "GET",
url: "http://gdata.youtube.com/feeds/base/users/devinsupertramp/uploads?orderby=updated&alt=rss&client=ytapi-youtube-rss-redirect&v=2",
dataType: "xml",
success: parseXml
});
$.ajax({
type: "GET",
url: "http://someotherdata.com/",
dataType: "xml",
success: function() { otherComplete = true; checkFinished(); }
});
});
function parseXml(xml) {
$(xml).find("item:first").each(
function() {
var tmp = $(this).find("link:first").text();
tmp = tmp.replace("http://www.youtube.com/watch?v=", "");
tmp = tmp.replace("&feature=youtube_gdata", "");
var tmp2 = "http://www.youtube.com/embed/" + tmp + "?autoplay=1&controls=0&rel=0&showinfo=0&autohide=1";
var iframe = $("#ytplayer");
$(iframe).attr('src', tmp2);
}
);
youtubeComplete = true;
checkFinished();
}
function checkFinished()
{
if(!youtubeComplete || !otherComplete) return;
// ... Unhide your content.
}
</script>
The browser will support multiple outbound calls but there is a cap per domain. Take a look at this related Q/A How many concurrent AJAX (XmlHttpRequest) requests are allowed in popular browsers?.
There are several good libraries for doing request scheduling including chaining and parallelizing AJAX calls. One good library is https://github.com/kriskowal/q, which provides async promises framework to enable arbitrarily complicated chaining of AJAX requests. Q minified is about 3.3KB.
// The jQuery.ajax function returns a 'then' able
Q.when($.ajax(url, {dataType: "xml"}))
.then(function (data) {
var parsedXML = parseXML(data)
...
// some other ajax call
var urls = [Q.when($.ajax(url2, {data: {user: data.userId}})),
Q.when($.ajax(url3, {data: {user: data.userId}}))];
// run in parallel
return Q.all(urls)
})
.then(function (data) {
// data retrieved from url2, url2
})

jQuery.ajax() sequential calls

Hey. I need some help with jQuery Ajax calls. In javascript I have to generste ajax calls to the controller, which retrieves a value from the model. I am then checking the value that is returned and making further ajax calls if necessary, say if the value reaches a particular threshold I can stop the ajax calls.
This requires ajax calls that need to be processes one after the other. I tried using async:false, but it freezes up the browser and any jQuery changes i make at the frontend are not reflected. Is there any way around this??
Thanks in advance.
You should make the next ajax call after the first one has finished like this for example:
function getResult(value) {
$.ajax({
url: 'server/url',
data: { value: value },
success: function(data) {
getResult(data.newValue);
}
});
}
I used array of steps and callback function to continue executing where async started. Works perfect for me.
var tasks = [];
for(i=0;i<20;i++){
tasks.push(i); //can be replaced with list of steps, url and so on
}
var current = 0;
function doAjax(callback) {
//check to make sure there are more requests to make
if (current < tasks.length -1 ) {
var uploadURL ="http://localhost/someSequentialToDo";
//and
var myData = tasks[current];
current++;
//make the AJAX request with the given data
$.ajax({
type: 'GET',
url : uploadURL,
data: {index: current},
dataType : 'json',
success : function (serverResponse) {
doAjax(callback);
}
});
}
else
{
callback();
console.log("this is end");
}
}
function sth(){
var datum = Date();
doAjax( function(){
console.log(datum); //displays time when ajax started
console.log(Date()); //when ajax finished
});
}
console.log("start");
sth();
In the success callback function, just make another $.ajax request if necessary. (Setting async: false causes the browser to run the request as the same thread as everything else; that's why it freezes up.)
Use a callback function, there are two: success and error.
From the jQuery ajax page:
$.ajax({
url: "test.html",
context: document.body,
success: function(){
// Do processing, call function for next ajax
}
});
A (very) simplified example:
function doAjax() {
// get url and parameters
var myurl = /* somethingsomething */;
$.ajax({
url: myurl,
context: document.body,
success: function(data){
if(data < threshold) {
doAjax();
}
}
});
}
Try using $.when() (available since 1.5) you can have a single callback that triggers once all calls are made, its cleaner and much more elegant. It ends up looking something like this:
$.when($.ajax("/page1.php"), $.ajax("/page2.php")).done(function(a1, a2){
// a1 and a2 are arguments resolved for the page1 and page2 ajax requests, respectively
var jqXHR = a1[2]; /* arguments are [ "success", statusText, jqXHR ] */
alert( jqXHR.responseText )
});

How to get the result of a jQuery AJAX call then call another function

Basically I am trying to call a function (function 1), that get the results from another function (function 2). And this function 2 is making an ajax call.
So the code would be like this:
function f1 () {
var results = f2();
}
function f2() {
$.ajax({
type: 'POST',
url: '/test.php',
success: function(msg){
}
});
}
I know that is I display an alert in the success function, I get the results. But how can we make this result be sended back?
I tryed to do something like this inside function 2 without success:
return msg;
thanks for your help
In theory, this is possible using jQuery's async: false setting. That setting makes the call synchronous, i.e. the browser waits until it's done.
This is considered bad practice, though, because it can freeze the browser. You should re-structure your script so you can do the relevant things in the success callback instead of f1. I know this is less convenient than what you do in f1(), but it's the right way to deal with Ajax's asynchronous nature.
You can forcefully make the request synchronous ( kinda losing the benefit of ajax ) but making your code work:
function f2() {
var ret = false;
$.ajax({
type: 'POST',
url: '/test.php',
async:false,
success: function(msg){
ret = msg
}
});
return ret;
}
Otherwise, you have to add a callback in your success function if you want to keep it asynchronous..
function f2() {
$.ajax({
type: 'POST',
url: '/test.php',
async:false,
success: function(msg){
doSomething(msg);
}
});
}

Resources