Javascript: call a specific function on function complete - javascript

I have a slow function that does an AJAX request:
function X(param1,param2){
var params={
type: "POST",
url: "./ajax/useful.php",
data: "param1="+param1+"&param2="+param2,
success: function(msg){
//do something
}
};
var result=$.ajax(params).responseText;
}
Everything works fine when I call X("asdf","qwerty").
Now, what I want to do is to be able to call function X as follows:
function X(param1,param2,function(){alert('hi');}){
var params={
type: "POST",
url: "./ajax/useful.php",
data: "param1="+param1+"&param2="+param2,
success: function(msg){
/////
//I want to be able call the function in the 3rd parameter (alert in this case)
/////
}
};
var result=$.ajax(params).responseText;
}
Now you might say why don't I just call alert('hi') directly inside the success. Sure I can do this, but I want to be able to vary what goes on inside the called function (not just a simple alert('hi'), depending on who's calling X.

You declare your X function like this:
function X(param1,param2,callback){
...use the callback like this:
success: function(msg){
callback();
}
...and call X like this:
X('a', 'b', function(){alert('hi');});
This works because your success handler is a closure over the data within your X function, including its arguments. It has a live reference to that information (even after X returns), and so later when the Ajax call completes, it can still use the callback argument. More on closures here: Closures are not complicated

function X(param1,param2,f){
var params={
type: "POST",
url: "./ajax/useful.php",
data: "param1="+param1+"&param2="+param2,
success: function(msg){
f();
}
};
var result=$.ajax(params).responseText;
}
should work.
You can no call X like this:
X(param1,param2,function(){dowhatever})

Related

setting and calling global var using ajax

I have a function that goes to a PHP script which returns the Server Operating System.
The script is literally dead simple:
<?php
echo (strpos(PHP_OS, 'Linux') > -1 ? 'Lin' : 'Win');
My goal is to be able to differentiate between operating systems so that I can declare a global path variable in my .js file for future uses.
This is what I've done so far:
function serverOS()
{
var os;
$.ajax({
url: '../scripts/ajax/detect-os.php',
type: 'get',
success: function(res)
{
os = res;
return os;
},
error: function(res) {alert('Major Error!'); console.log(res)}
});
return os;
}
console.log(serverOS());
The ending console.log outputs undefined - but if I console.log os inside of the success callback function, then it outputs what I expect.
According to this: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var
I should be able to do what I want with the above script but it doesn't seem to work. How do I go about setting and getting a global variable using ajax in JavaScript/jQuery?
AJAX operations are asynchronous. They will not block the rest of your JavaScript from executing.
The final return statement in your function attempts to return os immediately (before the AJAX operation has completed. Remove that return statement and in the success handler take care of all the logic to get the value back to the caller.
function serverOS() {
// The AJAX method will invoke the logging function no matter what.
// But, it won't happen until the AJAX call is complete.
$.ajax({
url: '../scripts/ajax/detect-os.php',
type: 'get',
success: function(res) {
returnValue(res);
},
error: function(res) {
alert('Major Error!');
returnValue(res);
}
});
}
function returnValue(val){
console.log(val);
}
serverOS();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Scott's Answer definitely works - but there does also seem to be an alternative I stumbled across. There's an AJAX property called async. Setting this to false in my function means it becomes a synchronous ajax call. Changing my function to this:
var os;
function serverOS()
{
$.ajax({
url: '../scripts/ajax/detect-os.php',
type: 'get',
async: false,
success: function(res)
{
returnValue(res)
},
error: function(res)
{
alert('Major Error!');
returnValue(res)
}
});
}
function returnValue(val)
{
os = val;
return os;
}
serverOS();
console.log(os); //this print Lin on my Linux machine.
ref: https://api.jquery.com/jQuery.ajax/

Housing $.AJAX inside a function and using a paramter as part of the "data" argument

I'm trying to create a reusable function that will allow me to call an AJAX request and use one of the passed in parameters as an argument in the data section of the AJAX call.
// Returns AJAX data for updating other fields based on a dropdown changing
App.prototype.OnDropdownChange = function (s, e, newId, ajaxParameter, ajaxRequestURL) {
// Create an AJAX request based on the parameters
$.ajax({
url: ajaxRequestURL,
data: JSON.stringify({ ajaxParameter: newId }),
type: 'POST',
success: function (data) {
// Return the data
return data;
},
error: function (data) {
// Error
return data;
}
});
}
The "ajaxParameter" would, ideally, hold the name of the parameter being passed up. So for example, "ajaxParamter" contains "theNewID" which is what my MVC controller is expecting as a parameter however when it's passed up it is shown as "ajaxParameter" and not the value inside.
How can I get this working?
EDIT
http://imgur.com/a/GSaPd
See here how it shows as ajaxParameter? What I want is that to be whatever I pass it in as.
You can do what you require, you just need to build the object using bracket notation to define the key.
However a much larger problem is your use of return within the success and error handlers. As the AJAX request is asynchronous you cannot return anything from it. Instead you need to provide callback functions to be executed under those events. Try this:
App.prototype.OnDropdownChange = function (s, e, newId, ajaxParameter, ajaxRequestURL, sCallback, eCallback) {
var data = {};
data[ajaxParameter] = newId;
$.ajax({
url: ajaxRequestURL,
data: data, // note no need to stringify the object
type: 'POST',
success: function (data) {
sCallback && sCallback(data);
},
error: function (x, s, e) {
eCallback && eCallback(x, s, e);
}
});
}
You can then call that like this:
x.OnDropdownChange(s, e, contactID, "CustomerContactId", "/Project/Project/GetCustomerContactDetails/", function(data) {
// success:
console.log(data);
}, function(x, s, e) {
// error:
console.log(x, s, e);
});
As you can see from this code, it's still quite verbose and is essentially now just a wrapper for $.ajax with very little benefit.
First of all when you are passing an obj in the data paramater of $.ajax request you don't need to stringify it unless i presume that you are storing like a JSON string in a database.
Second you can't return the data provided by the success, error, beforeSend and complete callback functions of the ajax request as they are a function itself and you are just returning the data to the callback function itself.
To get the data from the callback function to your original function you need to use a temporary variable to store the data you need to return
var myAjaxDatavalue = (function(myMethod,myData,myUrl){
var temp = null;
$.ajax({
method: myMethod,
url: myUrl,
data: myData,
async: false,
success: function(result){
temp = result
}.
error: function (xhr, ajaxOptions, thrownError){
console.log(xhr);
}
});
return temp;
})();
but beware as you can see one of the purpose of ajax, which being an asynchronous will be disable. This may lead to problems if your getting an enormous amount of data.

pass data through a ajax request to a callback function

Is it possible to pass data through a Ajax request to the Callback function without global variables?
for e.g. this request function should pass the passData through the callback function which should get also normal response data?!
function rquest(callback, passData){
$.ajax({
type: "POST",
url: someURL,
success: callback(passData)
});
};
function myCallback(data, passData){
var responseData = data;
var SomeOtherData = passData
//do Something
};
rquest(myCallback, "Hello World");
so "Hello World" should be in passData and data should be the normal response from server...if i do it in this way data is "Hello World" and passData is undefined.
Wrap the call to the provided callback in an anonymous function. Try this:
function rquest(callback, passData){
$.ajax({
type: "POST",
url: someURL,
success: function(data) {
callback(data, passData)
}
});
};
function myCallback(data, passData) {
var responseData = data;
var SomeOtherData = passData
//do Something
};
rquest(myCallback, "Hello World");
I found the answer in the below link - some more patterns are available to achieve this -
Adding some of the content from the reference answer.
The pattern you'd like to use could work if you create a closure inside your rssToTarget function:
function rssToTarget(element) {
return function (xmlData) {
// work with element and the data returned from the server
}
}
function doSomething(url, elem) {
$.ajax({ type: "GET",
url: url,
dataType: "xml",
success: rssToTarget(elem)
});
}
When rssToTarget(elem) is executed, the element parameter is stored in the closure, and the callback function is returned, waiting to be executed.
Reference link https://stackoverflow.com/a/1194187/3082706

Using JSON data retrieved via AJAX in separate function

Apologies if this is a duplicate question, I've followed some steps from another question which didn't seem to help me. I am trying to retrieve some JSON data, store part of the data into a variable and use that variable in a separate function outside of the AJAX request.
My expected response from the json data is http://localhost:8000/tutorials/retrieve/?page=2 (This response shows if I log the variable inside of the AJAX code) however the actual response I get when I try to log the variable from another function is as follows:
n.Event {originalEvent: MouseEvent, type: "click", timeStamp: 1436727171161, jQuery21304066238570958376: true, toElement: div#loadmore.recentTutorials…}
Here is the current code
var recentFirstPage = '';
function retrieveTutorials(){
$.ajax({
type: "GET",
url: "/tutorials/retrieve",
dataType: "json",
success: function(data){
**some unrelated parsing code here**
//Set the variable to what I need
recentFirstPage = data.next_page_url;
},
error: function() {
alert("An error occurred processing AJAX request.");
}
});
}
$('#main-content-wrap').on('click', '.recentTutorials', function(recentFirstPage){
//Does not return expected result
console.log(recentFirstPage);
});
When I click .recentTutorials I expect the console to log the data from JSON however it doesn't. Can someone help clear up my error(s)?
The reason that it doesn't log the data from JSON s that the call is asynchronous. This means that the function will execute top to bottom without waiting for the call to finish.
One method that's used is to leverage deferred objects which return a promise on completion. You can accept an anonymous function to the invoker function so that it's call back is executed within the scope of the click.
Observe:
function retrieveTutorials(){
return $.ajax({
type: "GET",
url: "/tutorials/retrieve",
dataType: "json"
});
}
$('#main-content-wrap').on('click', '.recentTutorials', function(){
//store our function call as an ajax promise
var promise = retrieveTutorials();
//wait for the ajax to return so we can mutate the data
promise.done(function(data){
//now our data will be properly
recentFirstPage = data.next_page_url;
});
});
It seems to me that you are trying to log the data before the ajax is completed. It`s better to use deferreds . Try this:
function retrieveTutorials(){
return $.ajax({ // will return deferred object
type: "GET",
url: "/tutorials/retrieve",
dataType: "json",
success: function(data){
**some unrelated parsing code here**
//Set the variable to what I need
recentFirstPage = data.next_page_url;
},
error: function() {
alert("An error occurred processing AJAX request.");
}
});
}
$.when( retrieveTutorials() ).done(function ( data ) {
console.log(recentFirstPage);
});
The parameter in your click handler is the last and final nail in your coffin. It's always the jquery event and you shouldn't handle it at all.
You do need to call the retrieveTutorials() function within the handler and you need to pass it a callback function that will be executed on success. So your retrieveTutorials() function will look something like this:
function retrieveTutorials(success){
$.ajax({ type: "GET", url: "/tutorials/retrieve",
dataType: "json",
success: success,
error: function() { alert("An error occurred processing AJAX request.");
} }); }
And your click handler:
$('#main-content-wrap').on('click', '.recentTutorials', function(){
retrieveTutorials(function(data){
console.log(data.next_page_url);
});
});
You can also use all the promise based goodness in the other anwers, but the above would be an idiom you'll see again and again.

using 2 ajax calls in one function

I want to make a ajax function to post data that I've loaded using another ajax function. I already discovered to use a callback function, but how do I pass data from the one function to the other. I've tried this :
getData(function{
$.ajax({
do stuff...,
data: dataArray,
do stuff...
)}
});
function getData(callback){
$.ajax({
do stuff...,
data: dataArray,
do stuff...,
success: function(data){
dataArray = fill array with stuff;
callback();
}
)}
};
looks like the array isn't available to the callback function...
Is this the solution I should think of, or is there another way to wait for the first ajax call to finish?
gr
Your code seems so complicated so I am writing a new one. You can make your own by looking at my code.
Try this;
$.ajax({
type: 'get',
url: 'http://geturl.com',
success: postdata(dataToPost)});
function postdata(dataToPost){
$.ajax({
type:'post',
url: 'http://posturl.com',
data: datatoPost
});

Categories