consolidating $.ajax - javascript

I have several ajax call on my page and I want to consolidate them into one function.
For now I have this type of function in several places:
function AjaxCallOne () {
//do something
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: TheURL,
data: "{'TheData':'" + JsonData + "'}",
dataType: "json",
cache: "false",
success:...
error:...
});
}
I want to write a single function that'll be used for all ajax calls like this:
function MyGeneralAjaxCall(TheData, TheURL, TheSuccessFunction, TheErrorFunction) {
$.ajax({ .... });
}
My question is this: if I do that and the user send two ajax calls, almost simultaneously, to the point where the second ajax call is made before the returning data of the first call comes back, will the success or error functions trigger for the the correct call. I'm worried that the success function that'll be executed won't be for the proper ajax call if the user triggers a second call before the first one is returned.
Thanks.

Your approach will work as you expect. Each success function, etc., that you pass in will be used individually by each associated AJAX call. (All of your parameters will be kept together.)

First, There's no single, global set of callbacks for ajax requests. Each ajax invocation gets it's own set of callbacks.
Secondly: $.ajax({...}) is your MyGeneralAjaxCall... if you are thinking you need a set of default options, a better way would be to set up a
var defaultoptions = { type: "POST", ...} //put default options, mimetypes, etc, here
(or something that returns that) and then wherever needed do:
var myajaxoptions = $.extend({},defaultoptions,myoverrides);
$.ajax(myajaxoptions);
That's much more extensible. No need to make up "men in the middle". Your approach will work, but I could easily see more than one MyGeneralAjaxCall being created. If you can manage not creating 5 or more methods like that MyGeneralAjaxCall, I suppose you'll be doing ok, but it could get nasty real quick.

Related

Return a controller method values using ajax

I have a function, that call a controller method using ajax
function CallService(data) {
$.ajax({
url: '#Url.Action("MyMethod", "MyController")',
type: 'GET',
dataType: 'json',
cache: false,
data: { 'serializedMessage': data }
});
MyMethod() returns a complex object and I need to display some properties on the page.
<script>
$(function(){
// create inputData
function (inputData) {
var myItem = CallService(inputData);
$('#name').text(myItem.Name);
};
});
</script>
As ajax returns nothing, I get an error message 'myItem is undefined' on the page. Can anyone explain how to return a variable and use it in JS functions, please?
I'm surprised you couldn't find an example of this anywhere already, but here goes:
There are a few different ways of defining callbacks which can run when the ajax call completes, as shown in the docs at http://api.jquery.com/jquery.ajax/. Here is one, based on the promises API:
function (inputData) {
$.ajax({
url: '#Url.Action("MyMethod", "MyController")',
type: 'GET',
dataType: 'json',
cache: false,
data: { 'serializedMessage': inputData }
}).done(function(result) {
console.log(JSON.stringify(result)); //just for debugging, to see the structure of your returned object
$('#name').text(result.Name);
});
}
One thing you need to grasp is that ajax calls run asynchronously, so the structure you had before will not work - you can't return anything directly from your "CallService" wrapper, which kind of makes it redundant. You have to wait until the ajax call completes, and run any code which depends on the result within (or within a function called from) the "done" callback.
As per the docs I linked to you can also define other callbacks for tasks such as handling errors, if you so desire.
You must use success:function(response){
}

Execute javascript function using jquery ajax that will change html, passing parameters at it and then execute another code

i would like to make an Ajax request like that:
function test(par1,par2) {
alert("add");
return(par1+par2);
}
$.ajax({
url: test,
dataType: "script",
data: 2,3,
success: function(data) {
alert(data);
}
});
I think that i am doing something wrong.
You need to call test, not reference it:
url: test("/mypath/", "somelocation.php")
The difference is in the brackets, and provided arguments. Without brackets you pass a function reference without executing it. This does not resolve to the executed value. With brackets you execute the function and pass to the url property the return value, which is what you want.
Of course, you need to decide what you pass to the function. In your case, you might have them in some variables.
Secondly, you need to change the value passed to data as well. It should be an object where each property corresponds to a parameter name:
data: {par1: 2, par2: 3}
jQuery will do the translation to the url format.
I have the impression your test function was intended to add parameters to the url, but since the data property is intended for that, you probably can do away with that function. Just assign the basic url to the url property, without parameters:
url: "/mypath/mypage.php"

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!
}):

jQuery Async Issue, Variable Assignment After GET Request

I'm sure the solution is staring me right in the eyes, but I just cannot see it. I am trying to load an object from an outside file source. I've tried it several which ways using jQuery's built in methods, but keep returning undefined. Is my issue the scope? I need partnerData right where it is because of other dependent methods in my script. I don't want to operate the rest of my site's functions from within the $.get callback. Any help is greatly appreciated, here's the code:
$(function() {
var partnerData;
$.get('data/partners.json', function(file) {
partnerData = $.parseJSON(file);
});
console.log(partnerData); /* returns undefined instead of object */
});
EDIT:
Thanks for all the feedback everyone. This is the solution I went with:
var partnerData;
$.ajax({
url: 'data/partners.json',
dataType: 'json',
async: false,
success: function(data) {
partnerData = data;
}
});
The reason why you're seeing undefined is because ajax requests are asynchronous by default. This means your get method gets invoked and the code flow moves down to the next statement while the request executes in the background. Your callback function is later invoked when the request completes.
Using callback functions is a common pattern used in situations like this. But you seem to be saying you don't want to do or can't do that. In that case, you could use async: false which would force the request to be synchronous. Keep in mind however, that your code will be blocked on the request and if it's a long-lived request, the user experience will degrade as the browser will lock up.
P.S. You shouldn't need to parseJSON - if response has the correct mime-type set, jQuery will intelligently guess the type and parse the JSON automatically. And in case the server isn't sending back the correct mime-type, you can also explicitly tell jQuery what the expected return data type is; see the dataType argument to $.get() .
One way you might modify your code, to force synchronous requests:
$.ajax({
type: 'GET',
url: 'data/partners.json',
success: function(file){
partnerData = $.parseJSON(file);
//ideally you would perform a callback here
//and keep your requests asynchronous
},
dataType: 'json',
async: false
});
function is proccessed to the end event when ajax is still being proccessed. insert it into callback function
$(function() {
var partnerData;
$.get('data/partners.json', function(file) {
partnerData = $.parseJSON(file);
console.log(partnerData);
});
});
I would say that your problem is the same of the one that I just solved, if $.get is AJAX! and it is setting a variable, to read that variable outside the callback you need to wait the response! So you have to set async=false!
console.log in synchronous and get is async.
try:
$(function() {
var partnerData;
$.get('data/partners.json', function(file) {
partnerData = $.parseJSON(file);
test();
});
function test(){
console.log(partnerData);
}
});

jQuery: insert html with javascript, waiting for it to run

I'm using $.ajax method to pull some html code and insert it into a 'div.listbox' element, using $('div.listbox').html() method.
I'm aware that .html will insert all HTML code, and execute all javascript code found under the HTML code.
What is actually happening:
$.ajax({
async: false,
url: 'ReturnSomeDataAsJSON',
data: {some_needed_data},
dataType: 'json',
success: function(data){
$('div.listbox').html(data.body)}
})
This data.body has a javascript that will make a call to an asynchronous function that will update an element inside the HTML under data.body.
Putting a .live function on the 'div.listbox' element, in order to listen to DOMNodeInserted event, I could see that the javascript method executed by the $...html(data.body) call updated 'div.listbox' element 6 times.
As this number could change, I can't just treat this as my solution, waiting to the element to change 6 times and then do what I want.
So I'm asking if it's possible to wait untill all javascript inside that .html call is executed before continuing to other javascript methods after the $.ajax call.
The only way would be to use a callback function inside your ajax-generated javascript, so you'd have:
//(ajax generated code)
<script>
...
$('div.listbox').css("color", "blue"); //For example, let's assume this code executes asynchronously
div_changed(); //This is the callback function
</script>
Then, in your main script you should have:
$.ajax({
async: false,
url: 'ReturnSomeDataAsJSON',
data: {some_needed_data},
dataType: 'json',
success: function(data){
$('div.listbox').html(data.body)
}
})
function div_changed(){
//Here put the code you want to be executed after changes are made
}
This is the only way, note that this is asynchronous.
Hope this helps. Cheers
JavaScript is a functional programming language meaning that you almost everywhere work with functions and can also pass functions as parameters. Let's describe your scenario: In scope A (parent element) you want to do something, but just when in scope B (child element) something happens and finishes. Only scope A knows what it wants to do, and only scope B knows when it finishes its job. So what do you do? Here are some solutions:
Hardcoding your logic of scope A in scope B (spaghetti code)
Get the function back from scope B and execute it in scope A (bad idea)
Pass the logic of scope A as a function to the scope B and let B be the agent to decide when to execute that.
The best method is the third item and this is the spirit of functional programming.
Solve by adding a listener to DOMSubtreeModified event, by doing:
$.ajax({
async: false,
url: 'ReturnSomeDataAsJSON',
data: {some_needed_data},
dataType: 'json',
success: function(data){
external_data = $(data.body)
var data_html = $(data.body)[0]
var data_script = $(data.body)[1].text
listbox_container = $('form#main_form div.listbox-container:nth(0)')
//fill body
listbox_container.html(data_html);
// attach listener
listbox_container.live('DOMSubtreeModified', check_listbox)
// eval script
eval(data_script)
// this script will (some time, asynchonously) update listbox_container
// by adding some data, that I need to deal with
}
})
function check_listbox() {
listbox_internal_ container = $('form#main_form div.listbox-container:nth(1)')
if (listbox_internal_container.length >= 1) {
// do what I want (deal with new data filled),
// because internal container (that will be created
// by the $.ajax call) now exists with some data filled by the
// eval(...) of the script
};
}

Categories