Ajax function doesnt complete before the second runs - javascript

I got an Ajax function that looks like this
function PersonAtlLawUpdate(personRef) {
var selectionPanel = $('div#SelectionPanel');
var fromdate = selectionPanel.find('input#FromDateTextBox')[0].defaultValue;
var timeSpan = selectionPanel.find('select#TimeSpanDropdownList').data('timespanvalue');
var url = "MonthOverview.aspx/OnePersonAtlLawUpdate";
$.ajax({
url: url,
data: JSON.stringify({ personRef: personRef, fromdate: fromdate, timespan: timeSpan }),
type: "POST",
contentType: "application/json",
dataType: "JSON",
context: document.body,
success: function (atlError) {
changePersonAtlStatusIcon(atlError, personRef);
},
error: function (xhr, status, errorThrown) {
//alert(errorThrown + '\n' + status + '\n' + xhr.statusText);
}
});
}
In one function I need to run this twice like this:
PersonAtlLawUpdate($(gMarkedCell).parent("tr").attr("personref"));
PersonAtlLawUpdate(pRef);
The problem that can be is that in some cases doesn't work 100%. The dom doesnt update in one of the functions. And I think it is because the other one "overwrites" it.
So how do I make sure that the second "PersonAtlLawUpdate" runs after the first one completes? Doesnt seems good to put a delay on it. And is it a good solution to set async to false in the ajax call?
EDIT,
tride like this and placed a console.log in my success. But "all complete" will run first of them:
$.when(PersonAtlLawUpdate($(gMarkedCell).parent("tr").attr("personref")), PersonAtlLawUpdate(pRef)).then(function (){console.log("all complete")});

You can just use a callback function so that it executes right after the first one has executed:
PersonAtlLawUpdate($(gMarkedCell).parent("tr").attr("personref"), function(){
PersonAtlLawUpdate(pRef);
});
Or maybe you can rethink the problem, and come up with a solution that doesn't require calling the same function twice. Maybe you don't really need to do this.

I think what #Kyokasuigetsu suggests is you need to alter the PersonAtlLawUpdate method so that is accepts an optional second parameter: a callback function that need to be called in the success callback.
function PersonAtlLawUpdate(personRef, cbFunc) {
var selectionPanel = $('div#SelectionPanel');
var fromdate = selectionPanel.find('input#FromDateTextBox')[0].defaultValue;
var timeSpan = selectionPanel.find('select#TimeSpanDropdownList').data('timespanvalue');
var url = "MonthOverview.aspx/OnePersonAtlLawUpdate";
$.ajax({
url: url,
data: JSON.stringify({ personRef: personRef, fromdate: fromdate, timespan: timeSpan }),
type: "POST",
contentType: "application/json",
dataType: "JSON",
context: document.body,
success: function (atlError) {
changePersonAtlStatusIcon(atlError, personRef);
if (cbFunc != null)
cbFunc();
},
error: function (xhr, status, errorThrown) {
//alert(errorThrown + '\n' + status + '\n' + xhr.statusText);
}
});
And than make the call as;
PersonAtlLawUpdate($(gMarkedCell).parent("tr").attr("personref"), function(){
PersonAtlLawUpdate(pRef);
});

Your example will work fine if you return your $.ajax calls from your PersonAtLawUpdate function.
$.when needs a reference to the ajax calls, so make sure you return the Deferred (the ajax call) from your functions
function PersonAtlLawUpdate(personRef) {
var selectionPanel = $('div#SelectionPanel');
var fromdate = selectionPanel.find('input#FromDateTextBox')[0].defaultValue;
var timeSpan = selectionPanel.find('select#TimeSpanDropdownList').data('timespanvalue');
var url = "MonthOverview.aspx/OnePersonAtlLawUpdate";
//SEE THE NEXT LINE
return $.ajax({
url: url,
data: JSON.stringify({ personRef: personRef, fromdate: fromdate, timespan: timeSpan }),
type: "POST",
contentType: "application/json",
dataType: "JSON",
context: document.body,
success: function (atlError) {
changePersonAtlStatusIcon(atlError, personRef);
},
error: function (xhr, status, errorThrown) {
//alert(errorThrown + '\n' + status + '\n' + xhr.statusText);
}
});
}
Use:
$.when(PersonAtLawUpdate(ref1), PersonAtLawUpdate(ref2)).done(function(xhrRef1, xhrRef2) {
//do stuff w/ results from both calls
//if you return something from the server,
//the results will be available in xhrRef1[0]
//and xhrRef2[0], respectively (order they
//appear in the when(), not in the order they execute
});

Related

jQuery .each containing AJAX - wait until next iteration

I have a jQuery .each statement that loops through a set of accordion/panels
$("div.section-data-source").each(function () {
populateAccordion($(this));
});
For each element, I call a function (populateAccordion) which has an AJAX query with it's own done() callback.
How can I tell my each function to wait until the populateAccordion() function is completed before moving on to the next iteration? Can I have a deferred against the function itself - or is there a way for the function to tell the each to iterate?
function populateAccordion(el) {
var apiName = el.attr("data-source-api-name");
$.ajax({
type: 'GET',
url: api_URL + apiName + "/" + id,
contentType: "application/json; charset=utf-8",
dataType: "json"
}).done(function(data) {
el.parent().find('.data-field').map(function () {
apiDataField = $(this).attr("data-field");
var itemValue = getApiDataValue(data, apiDataField, "Date");
$(this).text(itemValue);
});
});
console.log("FINISHED POPULATE");
};

jquery ajax inside loop return statusText error, Status 0 after certain time in IE

I m trying to update bulk of data one by one using Jquery ajax,so that i can show update progress. every thing goes well at beginning but after 5 min, it throw an error like in
Image while checking network request/respond:.
Error on error function of ajax:.
MainData is array of json object and is contain around 3000 number of json object.
function DoPost()
{
$.each(MainData, function (key, value) {
var mainCode = value.MainCode;
var companyCode = value.CompanyCode;
$.ajax({
url: "Allotment.asmx/DoAllotment",
data: "{MainCode:'" + mainCode + "', sNoOfAllotment:'" + noOfAllot + "',CompanyCode:'" + companyCode + "'}",
dataType: 'text',
contentType: "application/json; charset=utf-8",
type: "Post",
success: function (res){
Progress(res); // this funtion will show progress of update.
},
error: function (res) {
console.log(res);
}
});
});
}
I am using web service of asp.net webform
The issue could be maximum number of concurrent connections to same URL. You can schedule next $.ajax() call when current $.ajax() completes.
See also multiple, sequential fetch() Promise
function DoPost(value) {
var mainCode = value.MainCode;
var companyCode = value.CompanyCode;
return $.ajax({
url: "Allotment.asmx/DoAllotment",
data: "{MainCode:'" + mainCode + "', sNoOfAllotment:'"
+ noOfAllot + "',CompanyCode:'" + companyCode + "'}",
dataType: 'text',
contentType: "application/json; charset=utf-8",
type: "POST",
success: function(res) {
Progress(res); // this funtion will show progress of update.
},
error: function(res) {
console.log(res);
}
});
}
var copy = MainData.slice(0);
var res = (function re(value) {
return DoPost(value).then(function() {
return copy.length ? re(copy.shift()) : "complete"
})
})(copy.shift());
res.then(function(complete) {
console.log(complete)
}, function(err, textStatus, jqxhr) {
console.log(err)
});
The error 0x2ee2 is IE's representation of timeout error. The occurrence of this error shows that the server has stopped responding to the requests due to a high number of requests sent from the same client. This is the server avoiding DOS attacks from the client.
The proper method is to optimize the code and try to utilize the maximum available bandwidth in order to minimize the number of requests to the server.

What is the right way to use "context:..." in an AJAX call?

So I'm aware that there are a big amount of threads about AJAX and the use of the context but after hours of reading and trying I open a new Thread.
So I have this (shorten version) javascript function:
this.CallService = function () {
var Type = this.Type;
var Url = this.Url;
var Data = this.Data;
var ContentType = this.ContentType;
var DataType = this.DataType;
var ProcessData = this.ProcessData;
var ClipUrl = this.ClipUrl;
var CountMax = this.CountMax;
var Callback = this.Callback;
var SucceededServiceCallback = this.SucceededServiceCallback;
var FailedServiceCallback = this.FailedServiceCallback;
return $.ajax({
type: Type, //GET or POST or PUT or DELETE verb
url: Url, // Location of the service
data: Data, //Data sent to server
contentType: ContentType, // content type sent to server
dataType: DataType, //Expected data format from server
processdata: ProcessData, //True or False
context: this,
}).done(function (msg) {//On Successfull service call
SucceededServiceCallback(this, msg);
}).fail(function (msg) {
FailedServiceCallback(this, msg);
});
}
The Important part here are the context: this and the two callbacks done and fail. Im those two callbacks I give the this context to my callback functions:
this.SucceededServiceCallback = function (context, result) {
if (null != context) {
UpdateDebugInfo(context, "succeeded: " + context.DataType + " URL: " + context.Url + " Data: " + context.Data + " Result: " +result);
}
if (context != null && context.DataType == "json" && result != null && context.Callback != null) {
context.Callback(context, result);
}
}
Here the important part is that I use the context to see access the variables DataType, Callback, Url etc.
The Problem now is that the context is set to the last context used (it's an asynchron call so all the variable are the variable from the last call). So I'm pretty sure something is wrong with that context: this, part. I just don't know how to use this right. Thanks for your help.
tl;dr:
I use context: this in an Ajax call. Context is always set to the last "this" called. I want to use the "this" of the call.
You are "caching" all your variables before you fire each request, but in your SucceededServiceCallback function you are inspecting this.XXX - which is not the var Type it looks like you are expecting, but the actual this.Type itself.
What you could do is put these properties into an object and pass it as context, rather than your main object:
this.CallService = function () {
var context = {
Type : this.Type,
Url : this.Url,
Data : this.Data,
ContentType : this.ContentType,
DataType : this.DataType,
ProcessData : this.ProcessData,
ClipUrl : this.ClipUrl,
CountMax : this.CountMax,
Callback : this.Callback
};
var SucceededServiceCallback = this.SucceededServiceCallback;
var FailedServiceCallback = this.FailedServiceCallback;
return $.ajax({
type: Type, //GET or POST or PUT or DELETE verb
url: Url, // Location of the service
data: Data, //Data sent to server
contentType: ContentType, // content type sent to server
dataType: DataType, //Expected data format from server
processdata: ProcessData, //True or False
context: context,
}).done(function (msg) {//On Successfull service call
SucceededServiceCallback(this, msg);
}).fail(function (msg) {
FailedServiceCallback(this, msg);
});
}

On Save of when creating account record create a task (capturing current time and user in description field) using odata

**
function task()
{
var date=Date.now();
var accountid=Xrm.Page.data.entity.getId();
var entity = {};
entity.Description = date;
entity.Subject = "Hi.....";
entity.RegardingObjectId = {
Id:accountid,
LogicalName: "account"
};
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
datatype: "json",
url: Xrm.Page.context.getClientUrl() + "/XRMServices/2011/OrganizationData.svc/TaskSet",
data: JSON.stringify(entity),
beforeSend: function (XMLHttpRequest) {
XMLHttpRequest.setRequestHeader("Accept", "application/json");
},
async: false,
success: function (data, textStatus, xhr) {
var result = data.d;
var newEntityId = result.TaskId;
},
error: function (xhr, textStatus, errorThrown) {
alert(textStatus + " " + errorThrown);
}
});
}
//I try to get date from system and inserted in to task description but it showing.
Blockquote
Error bad request
Blockquote
so please help me out ,thanks in advance.
the statement :
var date=Date.now();
captures current date and time and returns as DateTime format.
here is where you went wrong
entity.Description = date;
entity.Description accepts sting only ..not datetime try converting the variable to string with toString() also check the other possible methods
check for demo
instead of var date=Date.now(); we can use `var date=Date();' it will work.
Instead of var date=Date.now(); we can use var date=Date();

backbone javascript setTimeOut method

im have a problem with method setTimeOut that call the function self and set a delay, the function should be called again and again after every request is done but it only runs once. It works without using backbone.js tho, don't know it doesnt work after integration with backbone.js. Any help is appreciated!
So this is a function in client that runs a GET request gets data from server, the request runs in a time interval(decided in the server), as soon as a data comes in, client gets it and the request runs again after.
getRequest:function() {
var XHR = $.ajax({
url: '/nextdocument',
type: 'GET',
async: true,
cache: false,
timeout: 11000,
success:function(data) {
var name = data.description;
var price = data.price;
console.log("read--> " + name + price);
setTimeout("this.getRequest", 1000);
if (data.ok == "true") {
data["ok"] = data.ok;
$.ajax(
{
url: "/customerdone",
data: JSON.stringify(data),
processData: false,
type: 'POST',
contentType: 'application/json'
}
)
}else{
//no document if no read in
console.log("error--> " + data.errorMessage)
}
}
})
return XHR;
}
The problem is that you're using "this" in your setTimeout call. You can't do this because "this" will be the global object when the timer executes the function you're trying to reference.
like others have suggested, you need to pass an actual function to your timer, not a string. then you can reference whatever function from whatever object you want.
probably, the function getRequest isn't being called. This is, as far as I think, because you are sending a string -- "this.getRequest" to the setTimeout function. As a rule of thumb, never pass string to this, pass functions. Although, it might be perfectly ok in some situations (i'd never recommend it anyway), here 'this' might be causing trouble. Use something like this:
getRequest:function() {
var fn = arguments.callee;
var XHR = $.ajax({
url: '/nextdocument',
type: 'GET',
async: true,
cache: false,
timeout: 11000,
success:function(data) {
var name = data.description;
var price = data.price;
console.log("read--> " + name + price);
setTimeout(fn, 1000);
if (data.ok == "true") {
data["ok"] = data.ok;
$.ajax(
{
url: "/customerdone",
data: JSON.stringify(data),
processData: false,
type: 'POST',
contentType: 'application/json'
}
)
}else{
//no document if no read in
console.log("error--> " + data.errorMessage)
}
}
})
return XHR;
}

Categories