Javascript call function once loop finishes and jQuery populates content - javascript

I'm trying to get my jQuery to work in this flow:
Parse json using $getJson
Loop through returned JSON and create divs for each JSON item
Once done, repeat but instead with another json file and append the results to the existing results.
But as of now I can't call another function AFTER the first loop is done, because the function gets called before the page is populated. How can I finish the populating loop, and then call another function?
I appreciate any help you can give me. Still learning as you can tell.
function test() {
var i;
for(i=0;i<=10;i++) {
$("div#test").append("<div id='"+i+"'></div>");
}
when_loop_is_done();
}
function when_loop_is_done() {
var i;
for(i=0;i<=10;i++) {
$("div#test div#"+i).append("<span>foo</span>");
}
}
Essentially I'm grabbing JSON from a separate page on my server, then looping through and populating the content using variables from that JSON object. The issue is no matter what I do, the second function always gets called before jQuery populates the content. So if I were to call an alert after the loop is done the page would pop up the alert and then load in all of the appended html.

Store your results in a variable or property. Then, use $(document).ready(fn) to wait for the page to finish loading and populate the page or finish your work when it has finished loading.

Your code should look something like this:
$.getJSON('/remote.json', function (response) {
// do the first loop using the response json
})
.done(function () {
// do the second json request and loop through the results
});
Any code you call inside the done() method's callback function will wait until the previous method in the chain is complete. You should definitely review the API documentation for $.getJSON: https://api.jquery.com/jquery.getjson/

Related

How pass data out of an AJAX function

I have a database with different link, I want to go fetch these link and put the inside an array.
I tried with the following code:
var amz=new Array();
function CreaArrayAmazon()
{$.ajax({
url: "php/amazon_affiliate.php",
success: function(data){
var leanamazon = JSON.parse(data);
for (i=0; i<leanamazon.length; i++)
{amz[i]=leanamazon[i].Link
}
}
})
}
I expect to find all the links in the "amz" array because it is a global variable, instead it saves links only when it is inside the AJAX function.
If I insert an "alert" inside the AJAX function (ex. alert(amz[i])) I can correctly see the data, instead if I insert an alert outside that I can't see anything, infact the amz array results to be empity.
Can someone tell me out to take that data out of there?
You might be misunderstanding what is going on here.
AJAX stands for Asynchronous Javascript and XML. Asynchronous means that your code doesn't always run in order.
In this case, your program functions like so../
function CreaArrayAmazon()
{
// Step 1: Make the Call
$.ajax({
url: "php/amazon_affiliate.php",
success: function(data){
// Step 3: When the call succeeds, execute the rest of this inner function.
var leanamazon = JSON.parse(data);
for (i=0; i<leanamazon.length; i++)
{amz[i]=leanamazon[i].Link
}
}
})
// Step 2: Continue Processing....
}
Step 2 happens far before Step 3. By the time your AJAX call finished, Javascript has already finished executing your CreaArrayAmazon call.
Instead, you need to have your inner function (Step 3) call an outside function to react to the new data you've received.

What is a better alternative to $("#myDiv").html(myResult); in this scenario?

I am currently using Ajax to update a feed of information. The Ajax should add to the current list of results rather than replace the existing results.
So far I have created the Ajax required to fetch the data from a database, but in the callback function I am using the following callback function
fetchPosts.onreadystatechange = function() {
if(fetchPosts.readyState === 4) {
$("#resultfeed").html(fetchPosts.responseText);
}
}
Obviously using $("#resultfeed").html(fetchPosts.responseText); in the callback function means that any prior results are overwritten on the page. How can I change this so that the results add to the current list of results?
Use append or prepend
$("#resultfeed").append(fetchPosts.responseText); // Adds at the end
$("#resultfeed").prepend(fetchPosts.responseText); // Adds at the top

Controlling an $.ajax function within a js "for" loop?

Here's my issue. I have a js function that performs an $.ajax call to fetch some data from a server. When it gets that data back, I need to pass control back to the browser in order to show an update to a div.
The js function is itself within a for loop, and I need to ensure that the for loop does not advance until the js function has updated the div and allowed the Browser to display that update, at which point the for loop advances and the js function (with its ajax call) is called again, continuing until the for loop test causes the loop to end.
I've tried many different approaches - callbacks, promises etc, but to date I can't seem to get a handle on ensuring that the loop doesn't advance until the js function gets its server data, updates the div, causes the browser to display that update and fully completes.
Here's a simple stripped-down version of the function:
function myFunction (email) {
var request = $.ajax( {
url: 'getit.php',
cache: false,
async: false,
method: "post",
timeout: 1000,
data: "requesttype=getemailname&email="+encodeURIComponent(email)
});
request.done(function(response) {
$("#myDiv").html(response);
});
}
and here's part of the js that calls it:
.....
var emailscount = emails.length;
for(var i=0;i<emailscount;i++) {
myFunction (emails[i]);
}
.....
So, my issues are:
1) myFunction must allow the browser to display the updated div html - I'm not sure how to achieve that?
2) the for loop should only proceed when myFunction has received the data back from the server, updated the div html, AND allowed the browser to display that div.
At the moment, I have set the $.ajax call async flag set to "false" to stop execution until the data comes back, but how do I ensure the browser displays the new div content, and that the for loop does not proceed to call myFunction again until the previous myFunction call fully completes?
Any help you can give me would be very welcome, as right now I can't get this all to work!
Sounds like you need a recursive function, not a for loop with synchronous ajax calls
(function myFunction(i) {
$.ajax({
url: 'getit.php',
method: "post",
timeout: 1000,
data: {
requesttype : 'getemailname',
email : emails[i]
}
}).done(function(response) {
$("#myDiv").html(response);
if (emails[++i]) myFunction(i); // continue when this one is done
});
})(0);
Thanks for everyone's help! I'm making good progress (including taking care of JQuery deprecations!) but have run into a further problem. As I need to hand control back to the browser in order to show the refreshed div as I recurse, I'm calling a setTimeout as follows:
var nextBitOfWork = function () {
return myFunction(email);
};
setTimeout(nextBitOfWork, 0);
where myFunction (which recurses) now returns a promise when it's done doing it's $.ajax call.
If I simply call:
return myFunction(email);
without the setTimeout function construct above, the promise is passed through and all my promises are captured and allow me to get the array output I need and everything works great. But without the setTimeout I don't get the browser refresh. Using it as above I get the div update refresh displaying, but seem to lose the promise and so the script continues and I don't get to fill the array I use to capture values as I recurse.
Any thoughts on how to make sure the setTimeout passes on the promise?
Thanks

Make sure JS file is loaded and JS function is called BEFORE calling another function

I have an issue with a tracking code that doesn't work properly since its called before a required JS script and function is loaded. Here is the situation:
Upon successful form submission (CF7 on WordPress) the following function is called right away.
function fn111Rooms(){
var email_address = document.getElementsByName("your-email")[0].value;
fnTransaction('Room booked', 'userid=' + email_address);
location.replace('http://example.com/thank-you');
}
The problem is, however, that the following script + function needs to be called beforehand to make everything work
<script type="text/javascript" src="http://www.example.com/Tracking.js"></script>
<script>fnPageHit('4ddc12d4344');</script>
This bit is placed in the section of each page but is not called again upon form submission since the form submits via AJAX (I believe that's the issue).
How can I include the script into the fn111Rooms and make sure everything is called correctly and in order. Really sorry in case that's a stupid question but JS is still confusing me from time to time.
EDIT: Would this work?
function fn111Rooms(){
// Loads the script
var fileref=document.createElement('script')
fileref.setAttribute("type","text/javascript")
fileref.setAttribute("src", "http://www.example.com/Tracking.js")
// Calls the required function
fnPageHit('4ddc12d4344');
// Does the rest
var email_address = document.getElementsByName("your-email")[0].value;
fnTransaction('Room booked', 'userid=' + email_address);
location.replace('http://example.com/thank-you');
}
And then just call the one function when submitting the form.. ?
You could take a look at jQuery.when()
Lets say you have a function you have to execute
function yourFirstFunction(){
$.post('/somewhere');
}
And a second right after first one finishes
function yourOtherFunction() {
//stuff
}
Then you can use the following construction
$.when( yourFirstFunction() ).then(function(data) {
yourOtherFunction()
})
i.e when yourFirstFunction is done (ajax request finished) yourSecondFunction will be executed
One way to do is applying infinite loop with some interval and checking following condition
fnPageHit && fnPageHit('4ddc12d4344');
so whenevr the ile gets loaded u will get function in other cases fnPageHit will be undefined hence it will not execute and will no cause error

I'm new to javascript and I'm fetching JSON data from url, I'm only able to access data in success function, Am I missing something?

Here is the code :-
var quiz;
function startQuiz() {
$.ajax({
url: 'get_quiz/',
cache: 'false',
dataType: 'json',
async: 'false',
success: function(data) {
quiz = data;
alert(quiz[0].q); // I'm able to access quiz here
},
}
);
}
startQuiz();
alert(quiz[0].q); // Not able to access it here.
I'm not able to access quiz here, am I mission something?, Whats wrong with this?
Ajax is assynchronous which can be an unfamiliar concept. Your code will run like this:
1. var quiz;
2. define function startQuiz;
3. call startQuiz;
4. do ajax call (and continue! don't block)
5. alert(quiz[0].q); // Not able to access it here.
-- ajax call comes back
6. quiz = data;
7. alert(quiz[0].q); // I'm able to access quiz here
Ajax is asynchronous, it doesn't block. This means that when you make the ajax call the callback doesn't actually get called until the ajax call returns, it doesn't block and wait. Instead the code will continue on.
Then later when the ajax call returns the data, your callback function will be executed.
Javascript does this by means of an event loop.
See it like this: steps 1-5 are part of the first event. 6-7 are part of the second event.
A cool thing about JavaScript is that in your callback you still have access to anything above it (like the variable quiz) because of scoping. This is called a closure. Your callback function closes around the scope and brings it with him to the next event.
AJAX calls are asynchronous, you should wait for the result to come back from the server. Either do all the work in a callback function or have a look on a promises library (I like Q promises library), which makes waiting for AJAX results very easy.
This is due to the asynchronous nature of JavaScript, once you call startQuiz() it executes and jumps back out and executes your quiz alert().
You have to access your quiz data explicitly after the callback is called to make sure you have access to it.
You also have to worry about scoping, as you may not be actually modifying the same quiz variable.
var quiz,
fetched = false;
$.ajax({
//blah
success : function(data){
fetched = true;
quiz = data;
}
});
setInterval(function(){
if(fetched){
//quiz is populated
}else{
//quiz hasn't be populated yet
}
},50);
Although not a clever example, I'm just trying to get the point across that startQuiz() doesn't wait for the ajax call. The A in AJAX mean asynchronous.
You should give jQuery deferreds a try which ist the preferred way of writing ajax related code since jQuery 1.5: http://javascriptplayground.com/blog/2012/04/jquery-deferreds-tutorial
Once you get the hang of it maybe will be easier to write and understand your code.

Categories

Resources