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
})
Related
I'm a beginner at javascript and pieced together the following code by searching online and lots of trial and error. I have simple data located in Google Fusion Tables and I would like to be able to pull data from the tables to use in equations. The only way I could get this to work was using JQuery/Ajax in non-async mode.
The code does what I want to do in non-Internet Explorer browsers but fails on MSIE8 (debugger shows that it gets stuck at the VsGM variable within the TestJax function).
Is there a way to get this work in IE? Am I totally on the wrong path, and if so is there a better way to retrieve this data (client side programming only)?
Here is my code:
<html>
<head>
<title>PSHA Output Page</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js">
</script>
<script type="text/javascript"
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDTvatTw0U-rSCpen_FnOMMk0a5Pggb0Os&sensor=false">
</script>
<script>
function myNumspull(myx,myy,vstable) {
var query = "SELECT * FROM " + vstable+" WHERE Lat="+myy+" AND Lon="+myx;
var encodedQuery = encodeURIComponent(query);
var VsGM, Lon, Lat, rows;
// Construct the URL
var url = ['https://www.googleapis.com/fusiontables/v1/query'];
url.push('?sql=' + encodedQuery);
url.push('&key=AIzaSyAm9yWCV7JPCTHCJut8whOjARd7pwROFDQ');
var myJax = TestJax(url, callback);
return myJax;
}
var callback = function(data, textStatus, xhr)
{
console.log ('from callback function '+myFunction(data, textStatus));
myFunction(data, textStatus);
}
var TestJax = function(url, cb) {
var data = 'Input values';
$.ajax({
url: url.join(''),
async: false,
cache: false,
dataType: 'text',
success: cb
});
console.log(VsGM,isNaN(VsGM));
return VsGM;
}
function myFunction(data, status) {
var rows = data.split(" ");
Lon = rows[18]; // Longitude
Lat = rows[21]; // Latitude
VsGM = rows[24]; //vs
console.log ('from myFunction'+ Lon, Lat, VsGM);
}
</script></head>
<body><script>
var VsTable = new Object();
VsTable['360'] = '1jN5wsiRuJwvK3dQA9ZK_5yW4r1NuhlzC-3jb9wo';
var x1 = -121.50;
var y1 = 38.50;
var k = '360';
var testnumber = myNumspull(x1,y1,VsTable[k]);
document.write ('results = '+testnumber);
</script></body></html>
It is likely because of the console.log() call.
In IE, you have to remove or comment out console.log() lines or many times it will not process. log() is a method of the 'console' object, and in IE the console object is not defined until the Developer Tools have been opened (press F12 to open the tools).
If you have Developer Tools open before the JavaScript is executed then it won't have this problem. Additionally, you can define a dummy/fallback console.log() object and method for the JavaScript to use when the browser does not currently have a console object defined (when the Developer Tools aren't open). See this StackOverflow question for some code: What happened to console.log in IE8?
I understand that this is an old question but I had the same problem in Internet Explorer 8 and 9 so I'm sharing the solution.
The ajax returned an error in IE8 and IE9.
This is because IE tried to download the file instead of simply reading it.
So in your ajax request, you simply need to specify the dataType which in this case is jsonp.
$.ajax({
type: "GET",
async: false,
cache: false,
dataType: 'jsonp',
url: query,
success: function(e) {
//...
},
error : function(e) {
//...
}
});
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.
EDIT: Ok, so the solution i came up with, is basically count the characters and see the difference between the numbers. One headache i had was related with the fact that the .html() didn't showed me the with the slash, instead, . Annoying....
function verifica(){
$.ajax({
type: "GET",
datatype: "html",
url: 'icallverifica.php',
data: "valor=0",
success: function(data) {
var verificando = $('#results').html();
var verificandox = (verificando.length);
var verificador = data.length;
if(verificandox != verificador){
$('#results').html(data);
}
}
});
}
I'm creating a little script using AJAX that retrieves data from a database. The problem is that I've used setInterval and it's refreshing all the time.
I don't have a problem with too many accesses to the database, my problem is that I want the content as static as possible until there are new entries on the database:
function verifica() {
$.ajax({
type: "GET",
datatype: "html",
url: 'icallverifica.php',
data: "valor=0",
success: function(data) {
var verificando = $('#results').html();
if (verificando != "<html>"+data+"</html>") {
$('#results').html(data);}
}
});
}
The function changes the #results div introducing the database information, the thing is that I don't want to change the div content unless there are any new entries.
What I did was check on the database and compare the previous content on the div, if it's the same, it will not overwrite.
BUT, i can't put data in html format...
Try changing the success handler to:
success: function(data) {
var verificando = $('#results').html();
if (verificando != data) {
$('#results').html(data);}
}
}
Did you try this instead ?
if ( verificando != data ){
$('#results').html(data);
}
You shouldn't need to concatenate <html> to the data while comparing it.
Such comparison is a overkill. You can basically check the ids associated to each result and then just refresh only the part which is new.
May be you can send the ids along with the ajax request itself and then filter out the response and send only which are the new results.
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 )
});
I am having a prob for ajax request in joomla using mootools.
var url = '<?php echo JURI::base();?>index.php?option=com_test&task=getselectmode&selectedid='+$('parent_question').value;
var params ={method: 'post',update:'test'};
var myAjax = new Ajax(url, params);
myAjax.request();
My prob is that, is there any to set onComplete event of the ajax request.
i have set it as below on above code but nothing happen.
onComplete: function(response) { alert('Response: ' + response); }
Can you please provide full code of how to use ajax using mootools 1.1 ??
Thanks in advance
just add the onComplete to the params object, no need to add the event seaprately. also, you can use this.response.text. it can all look a bit more compacted - depends on your preference. if you don't plan on reusing the object, just call it direct and don't assign it to a variable either:
new Ajax(url, {
method: "get",
update: $("someelement"),
onComplete: function() {
alert(this.response.text);
}
}).request();
if you do something with the response text, you may want to remove the update: bit. if you need to evaluate the response (as javascript), use evalResponse: true instead of eval(this.response.text);. also handy - evalScripts: true|false if you want to do something from the server side along with the response.
This should work:
var ajaxObj = new Ajax ('index.php?option=com_yourcomponent&view=yourview&format=raw', {
method: "get"
});
ajaxObj.addEvent('onComplete', function (data) {
// data is the response text
// use as desired
});
// this initiates the call
ajaxObj.request();
maybe:
var a = new Ajax( url, {
method: 'post',
data: { parfoto: foto },
onComplete: function( response ){
..........
}
}).request();