Explaining jQuery AJAX Success Method - javascript

Im trying to use this jQuery script and this is confusing me:
function CallService()
{
$.ajax({
type : varType, //GET or POST or PUT or DELETE verb
url : varUrl, // Location of the service
data : varData, //Data sent to server
contentType : varContentType, // content type sent to server
dataType : varDataType, //Expected data format from server
processdata : varProcessData, //True or False
success : function(msg) {//On Successfull service call
ServiceSucceeded(msg);
},
error: ServiceFailed// When Service call fails
});
}
The bit im confused about is the sucess object. The jQuery documentation says:
success(data, textStatus, jqXHR)Function, Array
A function to be called if the request succeeds. The function gets passed three arguments: The data returned from the server, formatted according to the dataType parameter; a string describing the status; and the jqXHR (in jQuery 1.4.x, XMLHttpRequest) object. As of jQuery 1.5, the success setting can accept an array of functions. Each function will be called in turn. This is an Ajax Event.
But this method signature looks nothing like the:
success : function(msg) {//On Successfull service call
ServiceSucceeded(msg);
}
Object that we seem to be passing in.
Questions:
1) What does function(msg){ServiceSucceeded(msg)} mean?
2) What is 'msg' in this context?
3) How on earth am I meant to know how to structure the method sugnature for sucess?

Perfectly reasonable question. :-) In JavaScript, you don't necessarily have to call a function with as many args as it defines, and you don't have to define as many args as you may get called with. Which can be confusing if you're used to more constrained environments. :-)
Answering specifics:
1) What does function(msg){ServiceSucceeded(msg)} mean?
It defines a function (an anonymous one) that accepts one named argument (msg) and calls ServiceSucceded passing in that arg. jQuery will call the function with the three arguments defined by the jQuery documentation for the success function, but this particular success function is only using the first of those (data). More about named functions vs. anonymous functions here.
2) What is 'msg' in this context?
The first argument to the function. jQuery's docs call this first argument data, but you can call it whatever you like.
3) How on earth am I meant to know how to structure the method sugnature for sucess?
You did the right thing, it's in the jQuery documentation.
This thing about function arguments can be confusing, so let's do some examples:
function foo(arg) {
alert(arg);
}
That's perfectly clear, I'm defining a function called foo that takes a single named argument, arg. And thus:
foo("Hi there"); // alerts "Hi there"
But I can also do this:
foo(); // alerts "undefined"
There, I didn't give any arguments for foo, and so within foo, arg is undefined.
I can also do this:
foo("Hi there", "again"); // alerts "Hi there"
I'm calling foo with two arguments, but foo only makes use of one of them.
I could define foo to use as many arguments as you pass in:
function foo() {
var index;
for (index = 0; index < arguments.length; ++index) {
alert(arguments[index]);
}
}
arguments is an automatic thing all functions have, which is a pseudo-array (it's not really an Array) of the actual arguments the function was called with. And so:
foo("Hi there", "again"); // alerts "Hi there", and then alerts "again"
You can even mix named and unnamed arguments:
function foo(arg) {
var index;
alert(arg);
for (index = 1; index < arguments.length; ++index) {
alert("[" + arguments[index] + "]");
}
}
So now
foo("Hi there", "again"); // alerts "Hi there" and then alerts "[again]"
Note the [] around the second alert, because I started looping with index 1 rather than zero.
arguments and named args are connected:
function foo(arg) {
alert("arg = " + arg);
alert("arguments[0] = " + arguments[0]);
arg = "Updated";
alert("arg = " + arg);
alert("arguments[0] = " + arguments[0]);
}
If I do foo("Hi");, that shows these alerts:
arg = Hi
arguments[0] = Hi
arg = Updated
arguments[0] = Updated
(It goes the other way, too, if you update arguments[0].)

The function is passed 3 parameters: data, status, and the jqXHR object. data is what is returned from the AJAX call, status is the HTTP status code (I think), and jqXHR is a jQuery wrapped XHR object.
In this script, they only care about the data parameter, and not the other two.
So using success: function(msg), they only get the data parameter. The other two are sent, but ignored.
ServiceSucceeded is just a function that is being called with the data parameter sent to it.
success: ServiceSucceeded could have also worked here.

It means the success handler invokes ServiceSucceeded with the response of the request.
msg contains the response from the request. msg maps to data in the jQuery documentation.
You need to look into the jQuery documentation for finding the signature.

This is an anonymous function.
It's like a regular function, but without a name.
msg is the function's first parameter.
By reading the documentation.

jquery Ajax is a way for you to communicate with the server (PHP, ASP, whatever). Let's assume you use PHP. the function "callService()" send a request to "varUrl" (validation.php, i.e) and get (or POST -> varType) the content (varContentType -> valdation.php?id=1231&whatever=soemthing). The purpose of this is to get some server side data without reloading the page. If you want the validation.php to echo some html, then the dataType in the Ajax function must be "html". See jquery.com for more info on dataType.
The success parameter is a function handler for the server response. Success is called if you get a response from the server corresponding to the dataType you asked (html, json, text, whatever). In that perticular case, if the server respond correctly, the function "ServiceSucceeded" is called with the attribute "msg" which is the server response you asked for.

1) That function is called if the AJAX request is successful i.e. a success status code is returned by the server being contacted.
2) I would assume that 'msg' is the data returned from the server. The other two arguments are not supplied and therefore not used.
3) Use the Jquery documentation, and fiddle around until you get what you want.

Even though the success function is defined as taking three parameters (as per the documentation you quoted), those three parameters are not mandatory - Javascript is very forgiving about this sort of thing; if you miss a parameter from a function call, it simply gets set to underfined, so as long as you don't try to use it, JS won't throw any errors.
The code you've provided only gives one parameter - msg - but in JS, this is perfectly valid; it just means that msg will be the data parameter defined in the docs, and textStatus and jqXHR will be undefined.
This is fine, as long as in your success function you don't actually want to use either of those parameters. If you want to use them, then pass them, but if not, it's fine to drop them. You're writing the success function, so you get to decide which of the three parameters to use.

Related

How does javascript function call work?

I have this piece of code below:
It makes a GET call to an URL, gets some object, and appends an image to an HTML tag.
function getDataFromApi(searchTerm, callback) {
const URL1 = `some url`;
const design = {
url: URL1,
data: {
"dog breed name": searchTerm
},
type: 'GET',
success: callback
};
$.ajax(design);
}
function displaySearchData(data) {
const allResultsLength = data.message.length;
const ranNum = Math.floor(Math.random() * allResultsLength);
const dogResults = data.message[ranNum];
$(`.js-search-results`).html(`<img src = ${dogResults}>`);
}
function watchSubmit() {
$('.js-search-form').submit(event => {
event.preventDefault();
let queryTarget = $(event.currentTarget).find('.js-query');
let query = queryTarget.val();
queryTarget.val("");
getDataFromApi(query, displaySearchData);
});
}
$(watchSubmit);
I get the getDataFromApi and watchSubmit but getDataFromApi(query, displaySearchData); isn't intuitive to me at all.
I've been writing Java, and it doesn't make sense to me how displaySearchData is getting called without the parameter - it seems that line should be getDataFromApi(query, displaySearchData(data));.
Can someone please explain how this is getting compiled & executed (basically how this is a legitimate syntax) in javascript?
Somewhere in the good'ol jquery, there lies this piece of code:
$.ajax = function(config){
...
// get the response from XHR request,
// and save it in, say, 'response'
...
// now check, if the response is OK 200
// and if so, execute next line
// which is basically - calling your displaySearchData method
config.success(response);
...
}
now, config is your design object, which has a property success which carries the reference to your displaySearchData method.
The data argument of method displaySearchData will now carry the reference to variable response passed in the method invocation config.success(response).
EDIT: the argument callback also carries forward the reference of the method displaySearchData to getDataFromApi
Concept to be noted:
functions can be passed in Javascript as arguments to another function, in which case we only need the referring variable to be passed as argument. Invocation parentheses () are not required.
function A(data){...};
function b(referenceToFunctionA){
...
referenceToFunctionA(someData);
...
};
// correct
b(A);
// wrong, because adding () after any function reference variable
// invokes the method immediately.
// in this particular case the returned value of the method A
// is passed as argument instead of the reference to method A itself.
b(A());
Welcome to JavaScript My Friend. Get ready to experience more magical weirdness as you continue to work on JS. Good luck.
What you need to look at is in the function getDataFromApi().
In that function, you have a "callback" parameter. This parameter is later added into $.ajax. This is a jQuery function that will provide some callback when a certain condition is matched (like before sending a request, when the response has been received,...). This $.ajax callback provide you with 3 parameters, one of them is data (which are being used, textStatus, and jqXHR. Usually, you only need to pay attention to the data since it contains the response from where you are requesting data.
So when the $.ajax success, the "callback" function will be called, which is the displaySearchData. And since $.ajax callback provides you with the data parameter, you can add them to the parameters of displaySearchData. Do note that you can add the extra 2 provided parameters if needed.
You can have a look at that function here: jQuery Ajax

Passing parameters to a function in Ajax

I'm following a tutorial on using Ajax with JavaScript, and this was the code we're making:
$('document').ready(function(){
$.ajax({
url: "AwesomeText.html",
type: "GET",
datatype: "Html"
})
.done(Success)
});
function Success(result){
$("p").append(result);
}
I got how it worked but there is one thing that confused me. We made a Success function to append the requested HTML file to the paragraph in the page, and then we passed a parameter called result, so from what I understand I can name the parameter anything and pass it as an argument and it will work. I took out success and passed in x as an argument and it still worked..
so my question is how does JQuery know it should store the requested HTML document in this parameter we're creating in this function? what if I have other functions will Jquery store the requested file to every function in it's parameter? I don't get how JQuery knows.
Also, there is a .done function in there, is that the same function that's explained here:
https://api.jquery.com/deferred.done/
why is it called deferred?
Default .done() callbacks will have 3 arguments passed through so based on your need you can use any of them in your success function with your own name.
three arguments passed are data, textStatus ,jqXHR
so your success function's first argument would be the response of the ajax call,i.e data recieved from the server,
second argument would be the status and third argument would the the jqueryXmlHttpRequest object.
based on your need you can access these objects in the same order
When you pass url to ajax it basically fetches that url and returns whatever it got at that url, AwesomeText.html in your case
and then it sends the content of that url to success function as a first parameter
Documentation
success = Type: Function( Anything data, String textStatus, jqXHR jqXHR
)
deferred .done(fn) method makes calling some method after the method on which .done was called [You can say Promise ] which makes synchronous calls
You can check following question for understanding the promises and .done() method
jQuery deferreds and promises - .then() vs .done()
The .done method accepts a "success" function as input.
Success: Function( Anything data, String textStatus, jqXHR jqXHR )
A function to be called if the request succeeds. The function gets
passed three arguments: The data returned from the server, formatted
according to the dataType parameter or the dataFilter callback
function, if specified; a string describing the status; and the jqXHR
(in jQuery 1.4.x, XMLHttpRequest) object. As of jQuery 1.5, the
success setting can accept an array of functions. Each function will
be called in turn.
So, the first argument (call it whatever - data / result / x / etc) will contain the reply of the server.
Source: http://api.jquery.com/jquery.ajax/

Why parameter gets assigned to callback?

I have a javascript function as:
function triggerUpload(success, error, callback) {
var options = {
type: 'post',
success: success,
error: error
};
$("input[name=file]").change(function() {
$(this).parent().ajaxSubmit(options);
});
if (callback) {
callback();
}
}
And i use it as:
triggerUpload(function() {
applyPostAjax(postUrl);
});
It works well as: When someone clicks on a Upload the triggerUpload event occurs with applyPostAjax as its parameter assigned to callback which can be kept null as its optional.
Note: These methods were coded by someone else and i can't get them clearly. I'm a newbie to javascript.
My issues is: i pass only one argument to this function. one would think that argument would get assigned to success. How/why does it get assigned to callback? What are these success, error parameters are here for?
Please explain
The parameters success and error are callback functions (same like the parameter you decided to call "callback") that gets executed when the ajaxSubmit method either successfully transmits the form data or encounters errors.
So, in your function call, you've supplied the success callback but not the error callback or callback callback. Since your function gets executed one can assume that the ajaxSubmit operation has successfully submitted the form.
One would be 100% correct to think that the argument gets assigned to success and not to callback.
Full documentation of the jQuery Forms Plugin available here: http://malsup.com/jquery/form/
and here: https://github.com/malsup/form
Specifically, the documentation of the success callback states:
success
Callback function to be invoked after the form has been
submitted. If a 'success' callback function is provided it is invoked
after the response has been returned from the server. It is passed the
following arguments:
1.) responseText or responseXML value (depending on the value of the dataType option).
2.) statusText
3.) xhr (or the jQuery-wrapped form element if using jQuery < 1.4)
4.) jQuery-wrapped form element (or undefined if using jQuery < 1.4)
What this means is that the correct prototype of the success function should be:
triggerUpload(function(response,status,xhr,form) {
applyPostAjax(postUrl);
});
Though it's perfectly fine to supply a function with more or fewer parameters because javascript allows functions to be called by fewer or more arguments than exist in their formal declaration. So if you're interested in only the result of the upload function you can just do:
triggerUpload(function(response) {
applyPostAjax(postUrl);
});
Or if you don't care about the response from the server you can just call it like how you did.
As others said, all the three success, error and callback should be functions. However, they have different purpose:
success - called once the ajax submitting is finished successfully
error - called once there is some error in the ajax submitting
callback - called no matter what is happening with the submitting. I guess this is added just to confirm that the change handler is assigned to the input field.
In other words calling triggerUpload doesn't submit the form. You just attach a handler to the file input button. Once you change it, i.e. you choose a file the form is submitted and you get a response after that.

How to assign use this in a construct

Im a bit of a beginner when it comes to javascript constructs. Im trying in jquery, but not with much success. The following is a reduces version of my code:
var field1 = {
fieldId:"#field1",
field:"",
init:function(){
this.field = this;
$.ajax({
type:"GET",
url:'some/url/to/get/values/from',
cache:false,
success: function(data){
alert(field.fieldId);
}
});
}
};
field1.init();
Basically i want to be able to print out field.fieldid inside the success event but i end up with something most definetly not expected. I would hate having to write field1.field.fieldid everytime also since that would ruin when i figure out how to use extends and similar things.
Can anyone help me get "#field1" out when i do the alert(field.fieldId) ?
This is a classic case of You must remember this. The simplest answer in your case is a local variable in your init function:
var field1 = {
fieldId:"#field1",
field:"",
init:function(){
var self = this; // <=== change here
$.ajax({
type:"GET",
url:'some/url/to/get/values/from',
cache:false,
success: function(data){
alert(self.fieldId); // <=== and here
}
});
}
};
field1.init();
Or alternately, use the context argument of the ajax function:
var field1 = {
fieldId:"#field1",
field:"",
init:function(){
// <=== change here (no `this.field = this;`)
$.ajax({
type:"GET",
url:'some/url/to/get/values/from',
cache:false,
context: this, // <=== and here
success: function(data){
alert(this.fieldId); // <=== and here
}
});
}
};
field1.init();
Basically, in JavaScript, the value of this during a function call is defined entirely by how a function is called, not where it's defined as in some other languages (C++, Java, C#, ...). When jQuery calls the success callback of the ajax function, it has to set this to something. By default, it sets it to an object representing the settings of the ajax call, but using context you can tell jQuery to set it to something else, allowing you to use this within the callback to mean the same thing as this when you call ajax.
The first solution takes advantage of the fact that the success callback is a closure over the context of the call to init (don't worry, closures are not complicated), and so by creating a variable (self) and giving it the value of this, we can reliably refer to the object via self within the closure (the success callback).
Ways in which this is set in JavaScript:
When you call a function by getting the function reference from an object property as part of the same expression as the call, this within the function call will be the object from which you got the property. So given:
var obj = {
firstName: "Fred",
speak: function(msg) {
alert(this.firstName + " says " + msg);
}
};
then
obj.speak("hi"); // alerts "Fred says hi", because `this = obj` within the call
Note that it has to be part of the same expression as the call. This does not work:
var s = obj.speak; // Getting a reference to `obj`'s `speak`
s("hi"); // alerts "undefined says hi", because `this` is not
// `obj` during the call
Using call or apply. These are features of all JavaScript functions. They let you call the function and explicitly set what this will be during the call. So given the obj above:
var s = obj.speak; // Getting a reference to `obj`'s `speak`
s.call(obj, "hi"); // alerts "Fred says hi", we explicitly made `this = obj`
// within the call
The only difference between call and apply is that when you use call, if you want to pass arguments to the function, you include them as discrete arguments to call as above (note we just passed "hi" as a second argument to call, and call passed it on as the first argument to the function). With apply, rather than an unlimited number of discrete arguments, the second argument is an array of arguments to pass to the function.
// Example 1: Passing no arguments, no difference.
// These calls do the same thing.
func.call(obj);
func.apply(obj);
// Example 2: Passing one argument (these calls do the same thing).
func.call(obj, arg);
func.apply(obj, [arg]); // note that it's in an array
// Example 3: Passing two arguments (these calls do the same thing).
func.call(obj, arg1, arg2);
func.apply(obj, [arg1, arg2]); // Again, the args are in an array

Run code after black box AJAX request returns

I have a function which makes an AJAX request to a server and returns relevant information after it completes.
I have another function which manipulates some variables in its namespace based on the returned information.
Currently, I am appending a 'callback' argument to the first function, which is called when the request completes. This, however, blurs the purpose of the first function - instead of being a 'getInfo' function, it's become a 'getInfoAndDo' function.
Ideally, I'd like to call the second function (a 'do' function, which calls the first function, a 'get' function) and does its thing.
I have looked around and found jQuery methods such as .ajaxStop and .ajaxComplete, but they seem to only to work when bound to DOM elements. Is there any way to do this entirely in javascript?
e.g.
function _getEventAttendance(uid, callback) {
var attendQuery = FB.Data.query('SELECT eid,rsvp_status,start_time FROM event_member WHERE uid = {0}', uid);
FB.Data.waitOn( [attendQuery],
function (args){
callback(args[0]);
}
);
}
function logAttendance(attendance){
console.log(attendance);
}
Currently, I am doing:
_getEventAttendance(123456789, logAttendance);
which seems ridiculous to me.
Is there a way to write the code such that I can change the code snippet inside _getEventAttendance / remove the callback argument:
FB.Data.waitOn( [attendQuery],
function (args){
return args[0];
}
);
and then make calls that are equivalently as simple as :
logAttendance.ajaxComplete(_getEventAttendance(123456789));
(I'm just making up the syntax for this, I have no idea how it's supposed to be written.)
$.when(<AJAX Request>).then(function(response){...});
Optionally use $.pipe() to filter response first.

Categories