I'm making ajax calls to an API server. I'm making a specific call to /getobjectdetails/ from multiple places in my code, so I thought I'd try to make it a bit cleaner, but this is the first time I've delved into callbacks like this. Here is the code I attempted:
let api = (function () {
return {
getObjectDetails(id, successCallback, errorCallback) {
$.ajax({
type: 'GET',
url: app.apiServerRoot + '/api/getobjectdetails/?Id=' + id,
beforeSend: function(xhr) {
xhr.setRequestHeader("Authorization", "Bearer " + user.authToken);
},
success: successCallback(data,s,xhrdata),
error: errorCallback(e)
});
}
}
})();
But when I call this as a test:
api.getObjectDetails(1008,function(data,s,x){console.log(data)},function(e){console.log(e)})
I get the following error:
Uncaught ReferenceError: data is not defined
at Object.getObjectDetails (api.js:13)
at <anonymous>:1:5
What am I doing wrong?
Change your ajax success parameter to:
{
...,
success: successCallback,
error: errorCallback
}
The way you were doing previously was executing the function directly.
You want to pass the reference of the function and not execute it.
For example when you bind a click event, you want to pass the reference:
button.addEventListener('click', myCallback);
And not
button.addEventListener('click', myCallback());
As the error points out, when you call successCallback, data isn't defined.
Try this:
let api = (function () {
return {
getObjectDetails(id, successCallback, errorCallback) {
$.ajax({
type: 'GET',
url: app.apiServerRoot + '/api/getobjectdetails/?Id=' + id,
beforeSend: function(xhr) {
xhr.setRequestHeader("Authorization", "Bearer " + user.authToken);
},
success: (data, s, xhrdata) => successCallback(data,s,xhrdata),
error: (e) => errorCallback(e)
});
}
}
})();
There isn't much difference between the arrow function notation and function declaration.
You could write either of these:
success: (data, s, xhrdata) => successCallback(data, s, xhrdata)
success: (data, s, xhrdata) => {
successCallback(data, s, xhrdata);
}
success: function(data, s, xhrdata) {
successCallback(data, s, xhrdata);
}
You need to pass success and error a function. You shouldn't call that function yourself.
When you put the parenthesis after the name of the function, it invokes it immediately. So instead of what you wrote, it should be :
let api = (function () {
return {
getObjectDetails(id, successCallback, errorCallback) {
$.ajax({
type: 'GET',
url: app.apiServerRoot + '/api/getobjectdetails/?Id=' + id,
beforeSend: function(xhr) {
xhr.setRequestHeader("Authorization", "Bearer " + user.authToken);
},
success: function(data, s, xhrdata) {
successCallback(data,s,xhrdata);
},
error: function(e) {
errorCallback(e);
}
});
}
}
})();
Related
I want to know which way is the best way to execute a function when a function with the ajax call has completed.
My code:
jQuery.when(AjaxCallToBokningar()).done(function () {
console.log("AjaxCallComplete");
});
function AjaxCallToBokningar() {
var url = `${_spPageContextInfo.webAbsoluteUrl}/_api/web/lists/getbytitle('Bokningar')/items
var call = jQuery.ajax({
url: url,
type: "GET",
dataType: "json",
headers: {
Accept: "application/json;odata=verbose"
}
});
//Done
call.done(function (data, textStatus, jqXHR) {
//Filling globalArray
window.globalBokningsArray = data.d.results;
});
//Fail
call.fail(function (jqXHR, textStatus, errorThrown) {
console.log('Loading Bokningar content faild: ' + textStatus + jqXHR.responseText);
});
}
Am I on the right track or is there a better way?
If you want to be able to make the Ajax call and then call a function when it's complete you can use a function reference as a parameter and do it like this...
function AjaxCallToBokningar(doneCallback) {
var url = `${_spPageContextInfo.webAbsoluteUrl}/_api/web/lists/getbytitle('Bokningar')/items
var call = jQuery.ajax({
url: url,
type: "GET",
dataType: "json",
headers: {
Accept: "application/json;odata=verbose"
}
});
//Done
call.done(function (data, textStatus, jqXHR) {
//Filling globalArray
window.globalBokningsArray = data.d.results;
doneCallback();
});
//Fail
call.fail(function (jqXHR, textStatus, errorThrown) {
console.log('Loading Bokningar content faild: ' + textStatus + jqXHR.responseText);
});
}
Then you can call it like this...
function ajaxCallComplete1() {
// this is executed after the 1st call is done - do something here
}
function ajaxCallComplete2() {
// this is executed after the 2nd call is done - do something here
}
AjaxCallToBokningar(ajaxCallComplete1);
AjaxCallToBokningar(ajaxCallComplete2);
or...
AjaxCallToBokningar(function() {
// this is executed after the call is done - do something here
});
You can also try something like this: (not tested)
function ajaxCallToBokningar() {
var url = `${_spPageContextInfo.webAbsoluteUrl}/_api/web/lists/getbytitle('Bokningar')/items`;
var options = {
url: url,
type: "GET",
dataType: "json",
headers: {
Accept: "application/json;odata=verbose"
}
};
return jQuery.ajax(options);
}
function updateBoknigarArray(data) {
window.globalBokningsArray = data.d.results;
}
function showError(jqXHR, textStatus, errorThrown) {
console.log('Loading Bokningar content faild: ' + textStatus + jqXHR.responseText);
}
ajaxCallToBoknigar()
.done(updateBoknigarArray)
.fail(showError)
I have one html element (elem1) and 2 JS functions (func1, func2) that hides and shows elem1 respectively. These JS functions make individual ajax calls and func2 is calling func1 internally.
Problem: I need to call func2, which internally calls func1. Calling func1 hides elem1. After calling func1, I want to show elem1. But this show is not working.
JSFiddle: https://jsfiddle.net/46o93od2/21/
HTML:
<div id="elem">
Save ME
</div>
<br/>
<button onclick="func1()" id="func1">Try Func1</button>
<button onclick="func2()" id="func2">Try Func2</button>
JS:
function func1() {
$.ajax({
url: '/echo/json/', //use the correct processing url here
type: "POST",
data: {}, // send in your data
success: function (data) {
//var aData = JSON.parse(data); // there is no data to parse
$('#elem').hide();
},
error: function (xhr, errmsg, err) {
alert('error');
}
});
}
function func2() {
$.ajax({
url: '/echo/json/', //use the correct processing url here
type: "POST",
data: {}, // send in your data
success: function (data) {
//var aData = JSON.parse(data); // there is no data to parse
func1();
$('#elem').show();
},
error: function (xhr, errmsg, err) {
alert('error');
}
});
}
Make func1 take a callback function that tells it what to do after it gets the response. func2 can pass a function that shows the element.
function func1(callback) {
$.ajax({
url: '/echo/json/', //use the correct processing url here
type: "POST",
data: {
json: ''
}, // send in your data
success: function(data) {
if (callback) {
callback();
} else {
$('#elem').hide();
}
},
error: function(xhr, errmsg, err) {
alert('error');
}
});
}
function func2() {
$.ajax({
url: '/echo/json/', //use the correct processing url here
type: "POST",
data: {
json: ''
}, // send in your data
success: function(data) {
func1(function() {
$('#elem').show();
});
},
error: function(xhr, errmsg, err) {
alert('error');
}
});
}
DEMO
I need to make an api call for 100 rows to populate description (which I prefer to do it in parallel). However some of rows might not have description in this case api will return 404. I need to show a warning message when there are a row or rows without description and remove those rows from modal data which means I need a complete callback or done callback. However the completeCallback is not being called and I "think" it's because some of rows doesn't have description.
Could you please tell me how to achieve that?
Here is my code:
function getDescription(processedData) {
$.ajax({
url: baseApiUrl + '/Summary?id=' + processedData.id,
type: 'GET',
dataType: 'json',
contentType: 'application/json',
success: function (data) {
processedData.SummaryDescription = data;
},
error: function (xhr, status, e) {
if(xhr.statusCode === 404){
processedData.SummaryDescription = '';
}else{
}
}
});
};
//Below line is in a look
parallelCallArray.push(getDescription.bind(null, processedData));
//Below line is out of loop
Async.parallel(parallelCallArray, function(err, result){
console.log('all calls completed...');
});
You're missing the callback parameter of your function(s) that are being executed in parallel. If you don't execute the callback, async will assume your functions haven't finished yet. Try something like this:
function getDescription(processedData, cb) {
$.ajax({
url: baseApiUrl + '/Summary?id=' + processedData.id,
type: 'GET',
dataType: 'json',
contentType: 'application/json',
success: function (data) {
processedData.SummaryDescription = data;
cb();
},
error: function (xhr, status, e) {
if (xhr.statusCode === 404) {
processedData.SummaryDescription = '';
} else {
}
cb(new Error(e));
}
});
}
Heylow everyone!
I have an ajax() call like so:
$.ajax({
type: "post",
url: "whatever.php",
data: {
theData: "moo moo"
},
success: function(data) {
console.log(data);
}
});
Is it possible to wrap this inside a custom function but retain the callback?
Something like:
function customAjax(u, d, theCallbackStuff) {
$.ajax({
type: "post",
url: u,
data: d,
success: function(data) {
//RUN theCallbackStuff
}
});
}
theCallbackStuff will be something like:
var m = 1;
var n = 2;
alert(m + n + data);
EDIT:
Got a recent upvote for this and I feel compelled to state that I would no longer do it this way. $.ajax returns a promise so you can do pretty much what i just did here in a more consistent and robust way using the promise directly.
function customRequest(u,d) {
var promise = $.ajax({
type: 'post',
data: d,
url: u
})
.done(function (responseData, status, xhr) {
// preconfigured logic for success
})
.fail(function (xhr, status, err) {
//predetermined logic for unsuccessful request
});
return promise;
}
Then usage looks like:
// using `done` which will add the callback to the stack
// to be run when the promise is resolved
customRequest('whatever.php', {'somekey': 'somevalue'}).done(function (data) {
var n = 1,
m = 2;
alert(m + n + data);
});
// using fail which will add the callback to the stack
// to be run when the promise is rejected
customRequest('whatever.php', {'somekey': 'somevalue'}).fail(function (xhr, status, err) {
console.log(status, err);
});
// using then which will add callabcks to the
// success AND failure stacks respectively when
// the request is resolved/rejected
customRequest('whatever.php', {'somekey': 'somevalue'}).then(
function (data) {
var n = 1,
m = 2;
alert(m + n + data);
},
function (xhr, status, err) {
console.log(status, err);
});
Sure i do this all the time. You can either execute the callback within the actual success callack or you can assign the callback as the success callback:
function customRequest(u,d,callback) {
$.ajax({
type: "post",
url: u,
data:d,
success: function(data) {
console.log(data); // predefined logic if any
if(typeof callback == 'function') {
callback(data);
}
}
});
}
Usage would look something like:
customRequest('whatever.php', {'somekey': 'somevalue'}, function (data) {
var n = 1,
m = 2;
alert(m + n + data);
});
function customAjax(u, d, theCallbackStuff) {
$.ajax({
type: "post",
url: u,
data: d,
success: theCallbackStuff
});
}
customAjax(url, data, function(data){
//do something
});
On this note, you can pass a complete function as a callback to this:
function customRequest(u,d,callback) {
$.ajax({
type: "post",
url: u,
data:d,
success: function(data) {
console.log(data); // predefined logic if any
if(typeof callback == 'function') {
callback(data);
}
}
});
}
// Then call it as follows:
function initiator() {
customRequest( '/url/to/post', 'param1=val', function() { alert( 'complete' ); })
}
Simply passing it as an anonymous function will work too.. Just for the sake of showing :)
I'd like to know if there is a better approach to creating re-usable ajax object for jquery.
This is my un-tested code.
var sender = {
function ajax(url, type, dataType, callback) {
$.ajax({
url: url,
type: type,
dataType: dataType,
beforeSend: function() {
onStartAjax();
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
callback.failure(XMLHttpRequest, textStatus, errorThrown);
},
success: function(data, textStatus) {
callback.success(data, textStatus);
},
complete: function (XMLHttpRequest, textStatus) {
onEndAjax();
}
});
},
function onStartAjax() {
// show loader
},
function onEndAjax() {
// hide loader
}
};
<script type="text/javascript">
var callback = {
success: function(data, textStatus) {
$('#content').html(data);
},
failure: function(XMLHttpRequest, textStatus, errorThrown) {
alert('Error making AJAX call: ' + XMLHttpRequest.statusText + ' (' + XMLHttpRequest.status + ')');
}
}
sender.ajax(url, type, dataType, callback);
</script>
You can set the basic options that you always have the same separately.
for instance if you always use the same thing here:
type: type,
dataType: dataType,
for those types, you can set them separately.
Here is how you do that type of thing:
$.ajaxSetup({
type: "POST",
contentType: "application/json; charset=utf-8",
data: "{}"
});
NOW those are set and you can simplify your individual ajax calls.
EDIT:
NOTE: Setting parameters to $.ajax override these defaults. Thus presetting “data” to an empty JSON string is safe and desired. This way, any $.ajax call that does specify a data parameter will function as expected, since the default will not be used. This helps avoid issues that can be difficult to find on a deployed site.
Here is what I did:
var ajaxclient = (function (window) {
function _do(type, url)
{
return $.ajax({
url:url,
type:type,
dataType:'json',
beforeSend: _onStartAjax
}).always(_onEndAjax);
}
function _onStartAjax()
{
console.log("starting ajax call");
}
function _onEndAjax()
{
console.log("finished ajax call");
}
return {
do:_do
}
}(this));
Example usage:
ajaxclient.do("get","http://...").done(function(data) {console.log(data);})
I'd probably go the whole hog and have an Ajax Object create.
var ajax = new MySuperAjax(url, data);
ajax.onComplete = function(){}
or similar. You seem to have a halfway between a function which has some defaults it extends with those you apss in and an object for it.