Synchronous javascript call to MVC 4 Controller action - javascript

I'm writing piece of code, and I need some functions to be executed sequential, I used ajax call but it is asynchronous and i faced problems
function GetLibraryActivities(libraryName, callback) {
$.ajax({
dataType: "json",
url: "/WorkflowDesigner/GetLibraryActivities/?libraryName=" + libraryName
}).done(function (data) {
console.log(data);
return data;
});
}
then I tried to work with callback function, but it didn't work too.
function GetLibraryActivities(libraryName, callback) {
$.ajax({
'url': "/WorkflowDesigner/GetLibraryActivities/?libraryName=" + libraryName,
'type': 'GET',
'success': callback
});
}
GetLibraryActivities("Petrophysics", function (data) {
petrophysicsData = data
});
when I try to use petrophysicsData variable under the code it returns unidentified , I need a mean to call a function in synchronous way, any help will be appreciated thanks.

Your main problem here is that you are trying to 'return' something from an AJAX callback. You cannot expect an Async AJAX function to return values to the script function that called it, because the function that called it moved on after the AJAX call started. That is the point of an Async call, it allows the javascript to move on and not have to wait for the server communication to complete.
The best way to handle this is to call all portions of a function in sequential order by using callbacks, never planning to use a return.
So, rather than returning data it would be best to instead call a function that processes data from within the callback function. It can be a little inconvenient, but when working with Async calls, it is best to assume that you can only go deeper into your call stack, rather than returning anything back out of it.
So, rather than your first option...you would want to do something like this instead...
function GetLibraryActivities(libraryName, callback) {
$.ajax({
dataType: "json",
url: "/WorkflowDesigner/GetLibraryActivities/?libraryName=" + libraryName
}).done(function (data) {
console.log(data);
ProcessResults(data);
});
}
Or, simply perform your processing within the callback.
Pre jQuery 1.8, there was the 'async' option, that would allow you to force Javascript to wait for the ajax call to process...but this locks up the browser while it is processing, and has since been deprecated.

If you simply return the Ajax promise like this:
function GetLibraryActivities(libraryName, callback) {
return $.ajax({
'url': "/WorkflowDesigner/GetLibraryActivities/?libraryName=" + libraryName,
'type': 'GET'
});
}
you can do this to use the value:
GetLibraryActivities("Petrophysics").done(function (data) {
// do something with petrophysics data
});
and chain them "sequentially" with then like this:
GetLibraryActivities("Petrophysics").then(GetLibraryActivities("Astrophysics")).done(function(pertro, astro){
// Do something with both results};
});
In this example both will load in parallel, but the done will only be called with both promises have completed (in any order).
If you have loads of these to load, you can use $.when to process multiple promises.

Related

Pipelining ajax http requests and execute the success function on Latest request only

I am using jquery ajax api to call a web method, and on success i am implementing a functionality like showHideDomElement.
function showHideDomElement(data)
{
if(data == 1 )
$('#selector').show();
else
$('#selector').hide();
}
and this is how i call it
function Validatebatch() {
$.ajax({
type: "POST",
url: getControllerURL("/Invoice") + "/ValidateBatch",
data: {
"Id": $('#someselector').val()
},
async: true, // i tried with 'false' but it affect performance
dataType: "json",
success: function(data) {
showHideDomElement(data);
}
});
}
The ajax request to Validatebatch function raised multiple times, so there are multiple active http request pointing the url completing at different time.
Due to Asynchronous behavior, the success callback can execute at different orders.
The order of finishing up is creating the problem. Please suggest a way that can bound the ajax request to behave/complete in the order it is executed (Please suggest other than jquery async property)
Thanks
First of, you have to rewrite your Validatebatch function so it return the Promise generated by the $.ajax call, e.g.:
function Validatebatch() {
return $.ajax({
then you must store the promise of each Validatebatch call and use it to trigger the next Validatebatch only after the previous has completed, you should have something like:
promise = Validatebatch(); // call Validatebatch the first time and store the returned Promise object
promise = promise.then(Validatebatch); // another call to Validatebatch, only triggered after the previous has ended
promise = promise.then(Validatebatch); // again, this third Validatebatch call will only happen after the second one has ended.

Carry out Javascript/jQuery functions in a sequence

I want to make some wine. And my function does:
function wine(){
growGrapes();
process(grapes);
makeWine();
bottle();
}
However, Since my functions often consist of $.ajax() request, some other functions get carried out first. I have used the success tool, but it helps for one ajax request only.
success:function(result){
//Some Code
}
What I actually want is a sequence.
Literally, grapes get processed before growing them. What is a easiest approach?
jQuery Deferred Objects & Promises are the way to go. http://api.jquery.com/category/deferred-object/
They supports running multiple tasks in parallel or series using $.when(PassArrayOfPromisesToRunInParallel) to run processes in parallel and promise.then() to run items sequentially.
Call the next function in the success handler of the $.ajax call of the previous function!
Example:
function growGrapes(){
// lines of code
$.ajax({
success: function(result){
// call next function here - process(grapes); and so on...
}
});
}
The above makes sure the functions get called sequentially after the other..
You can make your Ajax calls synchronous (in sequence) by ensuring you have async: false in your $.ajax() settings.
For example:
$.ajax({ url: 'url',
async: false,
dataType: 'json',
success: function(data) {
}
});
First solution :
Make your ajax call syncronous by setting async : false when setting up your ajax call
$.ajax
({
async : false,
/* other settings */
});
Warning: This solution causes the UI to hand on intensive processing. This should never be used when doing anything rigorous on the server. My recommendation for using this is to only use it in checking flags or loading simple data.
Second solution :
As stated in the comments, use jQuery promises to set up the ordering. Here is a tutorial
I'll try to come back and provide a code example for this solution soon
Third solution :
Make your next call the success handler, or call the next step from the success handler
$.ajax
({
success : NextStep,
/* other settings */
})
One solution is to use queue() function. This way you can execute as many functions as you want
var ajaxQueue = $({});
$.ajaxQueue = function(ajaxOpts) {
// queue the method. a second call wont execute until this dequeues
ajaxQueue.queue(function(next) {
// for this example I serialize params, but you can save them in several variables
// and concat into ajaxOpts.data
var params = method_that_get_params_and_serialize_them();
ajaxOpts.data = params;
ajaxOpts.complete = function() {
next();
};
$.ajax(ajaxOpts);
});
};
then your functions should be like this:
function growGrapes(){
$.ajaxQueue({
cache: false,
type: "POST",
url: "someUrl",
dataType: "json",
data: "", // we fill data inside ajaxQueue() method
success: function( response) {
//do things with response
}
});
}
If you want to keep it tidy and clean to let people see how your calls are made, you can simply pass a callback function to another like this:
function growGrapes(callback) {
$.ajax({
...
success: function (){
// Something
if (typeof callback === typeof Function) callback();
},
...
});
}
function wine(){
growGrapes(function (){
process(grapes);
});
}

Force a step in a function to happen only after ajax call has been completeed?

Is there a way to pause the rest of a function when you are waiting for a value to be returned from an asynchronous call with jQuery?
To achieve this "paused" behavior, you want to put the behavior inside the promise object. https://api.jquery.com/jQuery.ajax/
$.ajax({
url: "test.html",
data: myData
}).success(function() {
//put your code here this will only fire after it returns successfully
}).error(function() {
//This will fire if there is an error
});
What you are talking about would be a synchronous call, which is not recommended as it will freeze the UI.
Instead, use the callback provided in the jQuery call to perform the rest of your code:
function DoSomeCall()
{
$.post( "ajax/test.html", function( data ) {
//Do your follow on code in here, in the callback.
});
//Don't do any code here that relies on the AJAX being finished first.
}

Accessing JSON string Outside of Jquery Ajax Call

I am wondering is these is any way to access the results of a jquery ajax call in the form a traditional var set to function fashion. For example consider:
function getPoints(){
//An array of JSON objects
var Points;
$.ajax({
url: "js/retrievePointsDataJson.php",
dataType:'json',
type: 'POST',
}).done(function(data){
//console.log(data);
Points.append(data);
});
console.log(Points);
return Points;
}
The commented out console.log show the array of json objects whereas the outer one does not. Now, i have tries this:
var Points = $.ajax({ ...});
And i see the response text within a larger object, but am unsure how to access the responseText. console.log(Points.responseText) yields an undefined variable.
Is this possible with this approach? Here is another question that received a check mark with a similar issue.
I have another solutions, which is the encapsulate my code within the done() function and i will have access to all my data. I was just curious if what i am attempting to do is even doable.
Thank you.
yes it is possible, however, you must wait for the request to be complete before doing so. However, since you can't effectively force the return to wait until the data exists, you're only options are to return a deferred object instead, or re-write the function in such a way that allows it to accept a callback.
function getPoints(){
return $.ajax({
url: "js/retrievePointsDataJson.php",
dataType:'json',
type: 'POST'
});
}
getPoints().done(function(data){
console.log(data);
});
or
function getPoints(callback){
return $.ajax({
url: "js/retrievePointsDataJson.php",
dataType:'json',
type: 'POST',
success: callback
});
}
getPoints(function(data){
console.log(data);
});
Because the Ajax call is done asynchronously you shouldn't return it from the outside function. This would require that you somehow block until the asynchronous call completes. Instead you could pass in a callback function to the getPoints function that will handle the logic of using the points.
function getPoints(callback){
$.ajax({
url: "js/retrievePointsDataJson.php",
dataType:'json',
type: 'POST',
}).done(function(data){
callback(data);
});
}
The asynchronous nature of ajax can make things harder if your used to imperative programming, but it will make your user interface much more responsive.
The log you're calling in the outer function is working with an undefined variable because the function is asynchronous. You can't return it from getPoints because it won't have finished. Any work with the Points variable needs to happen inside the callback (the function passed to done).

Make sure ajax function finishes before 2nd non-ajax function fires

Similar to the question I just asked,
If I call an ajax function in jQuery and then a non ajax function how can I prevent the non-ajax function from firing until after the first ajax callback function has completed. Will declaring async: false in the first ajax function be enough?
If you're talking about this:
$.ajax({...});
someFunction();
where someFunction() won't occur until the AJAX call completes then you have three options:
Make the AJAX call async: false. Don't do this. It'll make your page unresponsive;
Put someFunction() in the complete/success/error callbacks of the AJAX call. This is the recommended approach; or
Use aplugin to manage a request queue eg Ajax Queue.
The first A in AJAX stands for "asynchronous". You just need to get used to the fact that these calls are asynchronous and stop trying to force a synchronous programming model on top of them. Adapt to the new programming model.
jQuery AJAX functions let you provide a callback that is only called after the request is finished. Call your non-ajax function as part of that callback.
You can use callback functions like this:
$("#btnSample").on("click", function (e) {
$.ajax({
url: 'some_url',
type: "GET",
async: true,
cache: false,
dataType: "JSON",
data: {
"p1": v1,
"p2": v2
},
success: function(result) {
//call you second function here!
}
}
});
});

Categories

Resources