Javascript functions wrong sequence - javascript

I am calling a function that loads JSON from a server and displays it in a div, that gets dynamically created in the DOM. After the created div is displayed, I want to do other stuff like parent.appendChild(x). Now it sometimes happens that the second step gets run before the first. I've tried to use this code, but it doesn't seem to work.
$.ajax({
url: firstfunction(),
success: function() {
parent.appendChild(x)
}
});
Note that firstfunction() loads JSON and displays it inside a newly created div.
Any ideas how to fix this problem?

You should use promises, so you wait to finish your Ajax request before moving on to another task (for your example manipulate DOM).
async function doAjax(ajaxurl){
const result = await $.ajax({
url: ajaxurl
});
return result;
}
//Call function
doAjax().then( data => doStuff(data) )
Async/Await with $.ajax example:
https://codepen.io/anon/pen/xpzJza

I fixed the problem by just using a synchronous httprequest.

Related

jQuery wait for a function to complete before new fires

I have two functions in jQuery that I want to fire in a specific order. The first function is an ajax function which updates a partial view. The other one is supposed to do some styling on the partial view, once the ajax function has completed - this function takes a parameter.
ajaxFunction();
stylingFunction(params);
I have tried the following:
ajaxFunction(function() {
stylingFunction(params)
});
Also, I have tried to use a callback:
ajaxFunction(stylingfunction(params));
ajaxFunction(callback)
{
//Do update
callback()
}
None of these do however work. The styling appears shortly where after it dissapears because the partial view is getting updated. Where am I going wrong here?
Both functions are written in my "parent" view.
You can use .done() and .fail() chained to the $.ajax call ...
I created a couple callback functions with psuedo-code inside the successCallback() since you said you only need to run the styling function "sometimes". You will want to test whatever condition inside that function to determine if you want to run the styling function. Hope this helps.
(function($) {
$(function() { //document.ready
$.ajax({ cache: false,
url: "/blah/vlah/lah",
data: { somedata: somedata }
})
.done(successCallback)
.fail(failCallback);
});
function successCallback(data) {
if (someCondition) {
stylingFunction(params);
}
};
function failCallback(jqXHR, status, error) {
console.log(jqXHR);
console.log(error);
console.log(status);
};
})(jQuery);
I created another gist which handles ajax event delegation, you may want to review and incorporate anything that seems helpful to your situation.
https://gist.github.com/inceptzero/a753d020648f49da90f8
I also created this gist on github for an ajax request queue which is a bit more elegant and robust.
https://gist.github.com/inceptzero/e64756f9162ca6aeeee5
Since you are using jQuery you could const ajaxFunc = callback => $.ajax({...}).done( data => callback) Also you could use async/await. You can read more about it on MDN.

Multiple ajax calls in jquery

I am using jquery for my project.
I have the following requirements:
I need to make a function call which invokes 5 other functions.
These 5 functions are ajax calls which work independent of each other. The ajax calls get data from server and appends values to a global object.
I am facing difficulty in finding whether all the ajax calls are done or not. After all the calls are done , I have to set it to localStorage and then load another html file.
What is the best way to do it?
If the number of ajax calls made are constant,You can use the following logic
COUNTER=5;
function reduceCounter(){
COUNTER --;
if(COUNTER == 0)
{
localStorage.Obj=JSON.stringify(Obj);
location.href="nextPage.html";
}
In each of your ajax calls , call reduceCounter() at .always();
eg:
$.ajax({
url: ..
type: 'GET',
dataType: 'json',
})
.done(){...
//set Obj
},
.fail(){...
},.always(){
reduceCounter();
}
mmm... Is it something you can do with jQuery Load, it makes sure everything loaded before you call any function or anything:
$(document).ready(function() {
//Make sure all DOMs loaded!
}):

Ajax and scope problems

I'm having some problems with AJAX and the scope of my data. I am new to Javascript and I'm not sure how to fix my problem.
var urlList = new Array();
$.ajax({
url: "http://localhost:3000/url",
success: function(data) {
alert(data.expressions.url); //This shows the correct result
urlList[0] = obj.expressions.dom;
}
});
alert(urlList[0]); //this shows undefined
I need the data that is in urlList[0] so i can use it at a later time. I think it's a scope problem.
Could someone point me in the right direction please?
Thanks
It's not a scope problem, but a timing problem. The ajax method is executed asynchronously. That means that calling it will not cause your program to wait until it is finished. This results in the alert being shown before the request is finished.
To fix this, put the request inside the success function as well. This is the proper place to handle the results of the request.
var urlList = new Array();
$.ajax({
url: "http://localhost:3000/url",
success: function(data) {
alert(data.expressions.url); //This shows the correct result
urlList[0] = obj.expressions.dom;
// This might work now, depending on what `obj.expressions.dom` is. This
// isn't becoming clear from your code. Usually you would use the `data`
// parameter of the success function, which contains the response body of
// the ajax request that has just finished.
alert(urlList[0]);
// of course you can call other functions as well. For instance, you
// could call
urlListChanged();
// ..which you can declare in global scope. This way, you can repond to
// changes from multiple sources, without having to duplicate code.
// It will all work, as long as you use the success handler as the trigger.
}
});
function urlListChanged()
{
alert(urlList[0]);
}
Your problem is one of chronology.
$.ajax fires an asynchronous request, meaning the rest of your code after it will continue to be executed before the request has resolved. Since urlList is populated only once the request resolves, your alert is firing too early.
Change
$.ajax...
to
var req = $.ajax...
and wrap your alert in a success callback:
req.done(function() { alert(urlList[0]); });
...or just move the alert inside your existing success callback.

forcing one javascript function to wait to run until the first has finished

Afternoon all, I am running into an issue where i need to run one function, then after that is finished, run the next, and do this for four functions, i have been at this for a while trying to find the correct syntax to layout my function calls in and cant seem to find anything to address this specific scenario.
html:
<div id = "putcontenthereafterajax">
</div><!--end putcontenthereafterajax-->
<div id = "putfooterhereafterajax">
</div<!--end putfooterhereafterajax-->
jquery:
$(window).load(function() {
function preload(arrayOfImages) {
$(arrayOfImages).each(function(){
$('<img/>')[0].src = this;
//alert("I cached "+this+"");
});
$('#progressbarinner').css("width","200px");//change the width of the inner progress bar div
}
function changecss(){
$('.hidetillcache').css("visibility","visible");//make the page visible
$('#loadingscreen').fadeOut("slow");
}
function contentajax(){
$.post("templates/content.php",
{
whatamidoing:"imgettingthecontent"
},
function(data){
$('#putcontenthereafterajax').after(''+data+'');
$('#progressbarinner').css("width","400px");//change the width of the inner progress bar div
});
}
function footerajax(){
$.post("templates/footer.php",
{
whatamidoing:"imgettingthefooter"
},
function(data){
$('#putfooterhereafterajax').after(''+data+'');
$('#progressbarinner').css("width","500px");//change the width of the inner progress bar div
});
}
preload([
'images/careers.jpg',
'images/careers.png',
'images/contact.jpg',
'images/facebook.png',
'images/footer.png',
'images/footerblack.png',
'images/footergrey.png',
'images/home.jpg',
'images/media.jpg',
'images/media.png',
'images/myitv3.jpg',
'images/newindex.jpg',
'images/newindex.png',
'images/services.jpg',
'images/twitter.png'
], contentajax(), footerajax(), csschanges());
});
basically i have a loading bar that fills up a bit after each function is finished which in turn requries each function to be ran one after another in the correct order, all the functions do work, the caching and the ajax and even the css changes work. however i cant seem to find a way to force them in the right order and to wait to run until the previous is finished in order to compliment the loading bar. Anyone have any ideas?
You want to chain asynchronous function calls.
Use jQuery's deffered.then method :
ajax functions, like $.ajax(), $.post(), $.get(), return a Deferred object.
You can use this in your case :
function contentajax(){
// add the return instruction to return the Deferred object
return $.post("templates/content.php", {... });
}
function footerajax(){
//same here
return $.post("templates/footer.php", { ... });
}
// chain the deferred calls :
contentajax()
.then( footerajax() )
.then( csschanges() )
If you also want to wait for the loading of the images to complete, you can still use this Deferred abstraction by wrapping the loading mechanism inside a single Promise. I googled around and found this gist (due credit should be given to the author : Adam Luikart).
Try to use callback function.
Instead of using .css try using .animation({'':''},200,function(){"........another function here......"})
Same with fadeOut as .fadeOut(200,function(){".....another function here........."})
So at the end you will only call contentajax().
Hope that helps.
By default your ajax calls are async. You can't guarantee the order of returns async. It sounds like you want execution in synchronous order. Either use
async: false
in your ajax calls, or use each next function as a success callback to the current one and don't loop through them in preload.
success: function(data, textStatus, jqXHR)
{
successCallback(successCallbackArgs);
}

How to make synchronous AJAX calls in greasemonkey?

I have a list of URLs and need to load each page, one after another.
This is my main function that i have in my Mind.
mainFunction() {
loop { // Loop through URL list
oPage = func1(URL); //Get page contents
aResult = func2(oPage); //Analyse the contents
func3(aResult); //Do current page modifications
}
}
func1 uses GM_xmlhttprequest, which is asynchronous, so oPage results in 'underfined' as function ends BEFORE the contents of a page could be retrieved.
func2 also uses GM_xmlhttprequest, so even no matter if oPage was undefined, aResult will be undefined too.
Any ideas on how to make all of this work?
func1 func2 and func3 should be reusable throughout the script, each of these functions may be used independently or together in different parts of script.
Is there any reason why you need to use Greasemonkey specific functionality? Are you doing cross site requests or something that specifically requires it? Looking at the Wiki for Greasemonkey, I can't find the option to set asynchronous to false.
Your easiest option is to include JQuery with your Greasemonkey script and use JQuerys AJAX functionality. Ofcourse, this can be done without JQuery, however, cross browser incompatibility in this area is quite the pain to handle manually.
Using JQuery, your code would look something like this:
function func1(url) {
var result;
$.ajax({
type: "GET",
url: url,
async: false,
success: function(data){
result = data;
}
});
return result;
}
and you would declare your variable oPage like this:
var oPage = func1(url);
The rest I think you can figure out yourself, good luck.
Normally you would put the calls inside of the xmlhttprequest's response handler, such that it returns immediately, and when it does get that page it then executes the required code.
If you really need to make them happen in a specific order, you can make the return for the first call the second, etc.
var urls = [];
(function recursive(list)
{
if (list[0]) // the list is not empty
GM_xmlhttpRequest({ // that would be "func1"
"url" : list[0], // first url in the list
"onload" : function(xhr)
{
var oPage = xhr.responseText, // page contents
aResult = func2(oPage); // analyse the contents
func3(aResult); // do current page modifications
list.shift(); // remove the first link of the list
recursive(list); // go to the next url in the list
}
});
else
alert("end of list");
})(urls);
haven't tested it but you got the idea

Categories