I am overriding the JQuery Ajax XHR object with my custom implementation in order to 'fake' serquest to server and response from server.
I created simple example of what I try to achive in JS fiddle - in JS part I am defining very simple, global sendAjax() function that suppose to call server using $.ajax():
window.sendAjax = function() {
var jqxhr = $.ajax({
url: "/ServerResource.txt"
});
jqxhr.done(function (data, textStatus, jqXHR) {
//this is never called
alert("done !")
});
jqxhr.fail(function (jqXHR, textStatus, errorThrown) {
//this is never called
alert("fail " + errorThrown);
});
}
also I try to substitute JQuery ajax xhr object using my own XHR where I replaced 'send()' method with my own implementation that suppose to return some data instead of XHTTPrequest - for the now in JSfiddle I am going to return imediately 'sucess' response. The problem is that the done or fail functions do not react on my response at all :(
Here is my redefinition of XHR
//reload jquery ajax
var originalXhr = jQuery.ajaxSettings.xhr;
$.ajaxSetup({
xhr: function () {
var req = originalXhr();
var deferred = $.Deferred();
var promise = deferred.promise(req);
if (req) {
// Add your progress handler
var _send = req.send;
req.send = function (headers, complete) {
//the one below does not work
setTimeout(function () {
deferred.resolve("Resolve promise", "OK", req);
}, 200);
}
var _open = req.open;
req.open = function () {
console.log('OPEN AJAX called');
}
}
return promise;
}
});
I probably do something and $.Deferred does not work in the way I wont it, but I cannot figure what is wrong so far.
Here is JS fiddle http://jsfiddle.net/ZwPXs/ - might be you have some ideas?
Best regards, Artem
Related
I want to make a convenience method for my Ajax calls as it is used extensively in the project.
As of now a typical call in the project looks like this.
$.post(
"url",
{
param1: value1,
param2: value2
},
function (data) {}
);
This call is repeated multiple times in the project with different parameters so I would like to be able to create a function to which I can pass the parameters and it will handle the entire Ajax call without me having to write the code every time.
Expected Output:
var data= {firstName:"John", lastName:"Doe", age:46};
do_ajax_request(data);
The function do_ajax_request in turn contains the actual Ajax code which makes the actual request and handles the result.
If possible I would also like for it to return a callback in case I need to perform any extra operations, would a promise work for that?
This would be a global function so I can access it from any JavaScript file.
So many complicated answers for something jQuery supports out of the box. Turning my comment to an answer.
You are basically just coding a wrapper for a wrapper so you do no have to recode some basic lines. No harm in that since it is easy to make the change in one place vs many.
So defined your function and just return the Ajax object that jQuery has. You can than use the done, fail, always methods.
function do_ajax_request (data) {
return $.post("url", data);
}
do_ajax_request({"foo":"bar"})
.done( function(){})
.fail(function(){})
do_ajax_request({"foo":"bar"})
.done( function(){})
.fail(function(){})
If you want to have common code inside, you can do that too, basic idea for an error handler...
function do_ajax_request (data) {
var xhr = $.post("url", data);
xhr.fail(function () {
console.log(arguments)
});
return xhr;
}
I have written several jQuery plug-ins for use in my projects, and have brought along my ajax call method in nearly everyone. Here is a snippet of it from one of my projects. Enjoy!
Method Signature:
obj = An object you want to pass to the ajax call in the data parameter. Pass null if not needed.
method = ajax methods: POST, GET, PUT, DELETE, etc. Default is GET.
endPoint = Url to call.
returnType = html, json, text, etc.
success = callback method when the call is successful.
beforesend = method to call before the send. This is useful when you need to set headers before a call.
failure = callback method when the call is unsuccessul.
var _api = {
call: function (obj, method, endPoint, returnType, success, beforesend, failure) {
obj = obj === null || undefined ? {} : obj;
$.ajax({
method: method || 'GET',
data: !$.isEmptyObject(obj) ? JSON.stringify(obj) : null,
contentType: function () {
switch (returnType) {
case 'json':
return 'application/json';
case 'text':
return 'text/plain';
case 'buffer':
return 'arraybuffer';
case 'html':
default:
return 'text/html';
}
}(returnType === 'json' ? 'application/json; charset=utf-8' : ''),
url: endPoint,
dataType: returnType,
beforeSend: function (xhr, obj) {
if (beforesend) {
beforesend(xhr, obj);
} else {
_api.showLoader();
}
}
}).done(function (data, textStatus, xhr) {
if (success) success(data)
}).fail(function (data, textStatus, xhr) {
if (failure) failure()
}).always(function () {
// Implement code here that you want to run whenever the call is complete regardless of success or failure.
});
}
}
You could create a prototype to with a constructor to handle the input - make the request and handle the response:
ajax.requests = function ( data ) {
this.data = data;
return this.doRequest();
};
ajax.requests.prototype = {
doRequest : function () {
var _this = this;
$.ajax({
data: _this.data
}).done(function(data) {
Handle response and return!
});
}
};
// USAGE
var response = new ajax.requests( yourData );
By returning the $.post, you can use a callback like .done(), chain them together with .then(), etc.
function do_ajax_request(data) {
return $.post( ... ); //RETURN the object
}
var myData = { ... };
do_ajax_request(myData).done(function(result) {
console.log("AJAX complete: " + result);
});
Just another take on this that maybe you hadn't considered. Rather than trying to wrap what is essentially already a wrapper, consider encapsulating your common functionality, like handling errors and dealing with results and using this when executing an ajax request with the existing jQuery ajax wrapper(s)
function handleError(e){
// your common error handling
}
function handleResult(result){
// your common result handling
}
// then every time you execute a request, use your shared functionality
$.post(url, data)
.fail(handleError)
.done(handleResult);
Using code below, you'd need to import config object or declare on top of the functions.
I made two versions for POST and GET respectively
function getJSON(param, absoluteRestUrl = '') {
if (!absoluteRestUrl) {
absoluteRestUrl = config.adminRestEndpoint; // defaultUrl
}
return new Promise(async (resolve, reject) => {
let res = null;
res = await $.getJSON(absoluteRestUrl, param);
resolve(JSON.parse(JSON.stringify(res)));
});
}
function postJSON(param, absoluteRestUrl = '') {
if (!absoluteRestUrl) {
absoluteRestUrl = config.adminRestEndpoint; // defaultUrl
}
return new Promise(async (resolve, reject) => {
let res = null;
res = await $.post(absoluteRestUrl, param, null, 'json');
resolve(JSON.parse(JSON.stringify(res)));
});
}
I am trying to clean up my code by namespacing which is new to me. I have a very basic app that makes an Ajax request and then does a load of stuff with the response. The code is starting to look messy so I want to namespace it and then call the namespace function that takes the AJAX response as the argument.
1. Can and should this be done?
2. If so how, here is the code
var GETDATA = {
myAlert: "this variable is the property of a namespace",
// response?: ???? do i need to declare response var here somehow
myNSFunction: function () {
alert(this.myAlert)
}
//theFunctionIWant: function (response??) {
// takes the response from ajax request
// does some stuff to it.
//}
};
$(document).ready(function() {
$( "#my-form" ).submit(function( event ) {
$.ajax({
type: 'GET',
url: "http://localhost:3000/DATA"
})
.done(function(response) {
//GETDATA.theFunctionIWant();
});
});
Any help much appreciated.
var GETDATA = {
myAlert: "this variable is the property of a namespace",
myNSFunction: function () {
alert(this.myAlert)
},
theFunctionIWant: function (response) {
console.log(response);
}
};
$(document).ready(function () {
$("#my-form").submit(function (event) {
$.ajax({
type: 'GET',
url: "http://localhost:3000/DATA"
})
.done(function (response) {
GETDATA.theFunctionIWant(response);
}
});
});
Should you do this?
Difficult to pass a judgment without understanding your overall goal and the scale of things, but mostly, no. You have to ask yourself, what benefit does this really offer? I mean, the handler could even be a function itself, not necessarily namespaced. What is the justification for namespacing it?
Will you have a group of response processing functions that are similar? Are you trying to build a store of received responses and related functions that act on the responses? Are you worried about conflicts resolution of some sort that requires a namespace to resolve with? etc.
A better approach: Consider closures for a private scope.
var RequestProcessors = (function() {
var thisIsPrivate = "Ok",
thisIsPrivateToo = "Fine";
return {
processorOne: function(resp, arg) { /* logic here */ },
processorTwo: function(resp, arg) { /* logic here */ }
}
})();
I'm trying to make multiple calls to Ajax, i have fields like time intervals and no of calls to ajax under that time period. Now the problem is, while making multiple calls to same Ajax, there may be chances of merging of data with the other data that were send to Ajax earlier. I am not sure that it will happen.
Here my Ajax call.
callAjax = function () {
var dataIn = inObj.data || {};
var successFunc = inObj.success || function () {};
var passOn = inObj.passOn || {};
var myParams = {drape:1,type:'GET'};
myParams.url = this.homeComingUrl;
$.extend(myParams,params);
var data = this.fillAction(action,dataIn);
if (myParams.drape) { vidteq.utils.drapeSheer(action); }
var that = this;
var magicCall = $.ajax({
url:myParams.url,
type:myParams.type,
data:data,
success: function (response) {
// TBD we need better error handling
if (myParams.drape) { vidteq.utils.undrapeCurtain(action); }
successFunc(response,passOn);
},
error:function(response) {
if (myParams.drape) { vidteq.utils.undrapeCurtain(action); }
that.gui.io.handleError(response);
}
});
}
saveEvents = function () {
this.commitEditingEvent();
var dataEvents = this.collectEventsToSave();
//$('#calendar').fullCalendar('removeEvents');
var that = this;
if (vidteq.eTrainer==1) {
dataEvents = arguments[0];
}
if (!dataEvents.length) { alert("Nothing to save");return; }
this.callAjax('updateEvents',{
data : { events : JSON.stringify(dataEvents) },
success : function (response,passOn) {
that.handleGetEvent(response,passOn);
}
},{type:'POST'});
}
This may not be required for understanding the problem.
If any body can explain how Ajax handles multiple calls, then it'll really helpful.
First line, your anonymous function isn't saved and isn't ran. Then. In each function, what does this refer to ? What is this context ? Is this window or do you call your function like saveEvents.apply( jQuery ) ?
JavaScript is powerful, when your want to run XMLHttpRequest (Ajax uses it), scripts are called when an event happen, like "server is found", "request is send", "file is reading", "file loaded"... for each state of your request. Ajax by jQuery help you to request asynchronous. You can request as many Ajax request as you would like in the same time. The important is to create a function happen in success case.
In this success function, you receive data, you compute it, then this function may call another Ajax request, and so on. When you chain requests like this to get the same file, we call it Ressource.
Ressource uses Ajax which uses XMLHttpRequest.
you need to do asynic :false in your ajax method
function isLoggedIn() {
var isLoggedIn;
$.ajax({
async: false,
// ...
success: function(jsonData) {
isLoggedIn = jsonData.LoggedIn
}
});
return isLoggedIn
}
I'm using Django.
I have the following code
var done_cancel_order = function(res, status) {
alert("xpto");
};
var cancel_order = function() {
data = {};
var args = {
type:"GET",
url:"/exchange/cancel_order/"+this.id,
data:data,
complete:done_cancel_order
};
$.ajax(args);
return false;
};
The function var cancel_order is called when I press a button on the page. That url when accessed is does some things on the server side, which I can check indeed are done, and then returns a json specifying whether or not the request was successful. You get:
{'status':200, 'message':'order canceled'}
The problem is that the callback is never called. I would like to have the callback display to the user the thing that was returned from the server. But even the first alert("xpto") inside the callback is never executed. Why is that?
EDIT:
I have checked that this code:
var cancel_order = function() {
data = {};
var args = {
type:"GET",
url:"/exchange/cancel_order/"+this.id,
data:data,
complete: function() { alert("xpto"); }
};
$.ajax(args);
return false;
};
displays the same behavior as described above: everything goes great on the server side, but the callback isn't called.
Be sure nothing is messing with your debug tools [e.g. console.log], it may end up wrecking your js code, delivering unexpected results.
Why don't you change it to this:
function done_cancel_order (res, status) {
/* remains same */
};
I hope, this one would work for you!
Or just simply:
complete: alert("xpto");
I have created a function called save , when i call save function, I am getting success undefined or object Object
UPDATES:
updated to get he values jqxhr object that ajax returns
function save() {
return $.ajax({
type: "POST",
url: "foo.json",
data: json_data,
contentType: 'application/json',
success: function (data, textStatus, xhr) {
$('<div id="loading">Loading...</div>').insertBefore('#form');
},
error: function (jqXHR, textStatus, errorThrown) {
}
});
}
$(document).ready(function () {
$(function () {
$("#save").click(function () {
var jqxhr = save();
alert("success " + jqxhr.success);
alert("status " + jqxhr.status);
alert("status " + jqxhr.readyState);
});
});
});
For the upteenth time.
ajax is asynchronous.
Use a callback function.
Ninja edit by OP
First of all, there is no return statement within your save function, so it works as expected by returning undefined value.
Secondly, it won't work that way. You need to return the $.ajax call (which itself, returns a jqXHR object, where you can hook in and setup code for different events. Afterall, by default an Ajax request runs asyncronously.
in save()
return $.ajax({ ...
and later...
save().done(function( retValue ) {
alert('success ' + retValue);
});
Learn more about jQuerys Ajax and Deferred objects here and here.
May be this is causing the issue, as i see you are having 2 document ready handlers one in another.
/***/
$(function () { // <--------------------I think this doesn't has to be here,
// so remove it and try if this solves
// the issue
$("#save").click(function () {
var success = save();
alert("success " + success);
});
}); // <-------------------------------and this one too