Recently I faced an issue which can be closely described as using AJAX ajaxOptsAjaxFirst
inside sucess function of another AJAX ajaxOptsAjaxSecond
which is iterated by a loop. If you are familiar with ajax then skip the next paragraph.
For those of you who are not familiar with ajax, let me try to briefly explain AJAX. AJAX stands for Asynchonous Javascript. As it’s name suggests, it is used to send to and retrieve data from a server asynchronously (in the background) without interfering with the display and behavior of the existing page. See how to use ajax with jquery here.
I was runnig a javascript which called a function element_class_clicked
in loop for all the elements present on DOM (See code Below).
Also a refrence has to be passed to this function. As the code demands to call two ajax calls one after the other was done, so with the help of call backs we did that. The ajaxOptsAjaxFirst
call was internally (some_fn
) calling the ajaxOptsAjaxSecond
and all of this was done inside namespaces. Code with issues is as under:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
var NAMESPACE ={
SubpartNamespace : {
element_class_clicked : function(clicked_element){
var form_vals = NAMESPACE.SubpartNamespace.get_apparel_details(jQuery(clicked_element).children('.class1'));
ajaxOptsAjaxSecond = {
xhrFields: {withCredentials: true},
url: "http://"+server_name+"/link1/",
dataType: 'json',
crossDomain: true,
data: form_vals,
success: function(resp){
alert(resp)
//some code
},
};
var ajaxOptsAjaxFirst = {
url: "http://"+server_name+"/link2/",
dataType: 'json',
crossDomain: true,
data: form_vals,
success: function(resp){
if(resp.ready === true){
//some more code
NAMESPACE.SubpartNamespace.some_fn(some_data);
}
else{
console.log('Resp not ready for action');
}
},
};
loginAjaxOpts = {
url: "http://"+server_name+"/login_link/",
crossDomain: true,
xhrFields: {withCredentials: true},
success: function(resp) {
//console.log(resp);
if (resp.status === "authenticated") {
//some code
jQuery.ajax(ajaxOptsAjaxFirst);
} else {
console.log("Please login first");
}
},
};
jQuery.ajax(loginAjaxOpts);
},
some_fn : function(some_data){
//some more code
jQuery.ajax(ajaxOptsAjaxSecond);
//some more code
},
toggle_fn : function(eventObj){
eventObj.preventDefault();
if (AUTH_STATUS) {
var this_item = this.parentElement.parentElement;
if(jQuery(this).parent().siblings('canvas').is(':visible') == false){
NAMESPACE.SubpartNamespace.element_class_clicked(this_item);
}else{
NAMESPACE.SubpartNamespace.element_other_class_clicked(this_item);
};
} else {
console.log("Please log in first");
}
},
},
};
window.onload= function() {
$('.element_class').on('click', NAMESPACE.SubpartNamespace.toggle_fn);
$('.'+someClass+'').click(function(){
a=$('.element_class');
$.each(a,function(c){
if($(a[c]).parent().siblings('canvas').size()<=0){
$(a[c]).trigger('click');
//trigger click in this case will aslo call element_class_clicked(this_item) with same args
}else{
var this_item = this.parentElement.parentElement;
NAMESPACE.SubpartNamespace.element_class_clicked(this_item);
}
});
});
};
Here the problem was that sometimes on slower servers or clients on slower networks, before we recieved the response for ajaxOptsAjaxSecond
, the code would proceed ahead and thus give wrong results, as it would was loose the context for clicked_element
for that paticular response.
I tried to use many solutions and hacks, like setimeout , many other solutions mentioned on stackoverflow but none of them seemed to work for my problem. Then I solved it with by having simple abstraction for the ajaxOptsAjaxFirst
. Code is as under:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
var NAMESPACE ={
SubpartNamespace : {
seperate_ajax_fn: function(canvas, form_vals){
ajaxOptsAjaxSecond = {
xhrFields: {withCredentials: true},
url: "http://"+server_name+"/link1/",
dataType: 'json',
crossDomain: true,
data: form_vals,
success: function(resp){
//some code
alert(resp);
},
};
jQuery.ajax(ajaxOptsAjaxSecond);
},
element_class_clicked : function(clicked_element){
var form_vals = NAMESPACE.SubpartNamespace.get_apparel_details(jQuery(clicked_element).children('.class1'));
var ajaxOptsAjaxFirst = {
url: "http://"+server_name+"/link2/",
dataType: 'json',
crossDomain: true,
data: form_vals,
success: function(resp){
if(resp.ready === true){
//some more code
NAMESPACE.SubpartNamespace.some_fn(some_data);
}
else{
console.log('Resp not ready for action');
}
},
};
loginAjaxOpts = {
url: "http://"+server_name+"/login_link/",
crossDomain: true,
xhrFields: {withCredentials: true},
success: function(resp) {
//console.log(resp);
if (resp.status === "authenticated") {
//some code
jQuery.ajax(ajaxOptsAjaxFirst);
} else {
console.log("Please login first");
}
},
};
jQuery.ajax(loginAjaxOpts);
},
some_fn : function(some_data){
//some more code
NAMESPACE.SubpartNamespace.seperate_ajax_fn(canvas, form_vals);
//some more code
},
toggle_fn : function(eventObj){
eventObj.preventDefault();
if (AUTH_STATUS) {
var this_item = this.parentElement.parentElement;
if(jQuery(this).parent().siblings('canvas').is(':visible') == false){
NAMESPACE.SubpartNamespace.element_class_clicked(this_item);
}else{
NAMESPACE.SubpartNamespace.element_other_class_clicked(this_item);
};
} else {
console.log("Please log in first");
}
},
},
};
What it does is, it creates a stack for the seperate_ajax_fn
and thus saves the context for arguments.Thus this solution will even work for slower networks as it will wait for the response for ajaxOptsAjaxFirst
and pass corresponsing arguments which it had saved in stack. Here with just some restucturing of code in the Namespace we got the desired result.
Hope this helps someone. If you have any other approach which you think is preferable (easy to use/efficient) than above mentioned one then please do share. Thanks for reading the post. Happy coding…