Make ajax call dependent on another ajax call - ajax

I would to avoid nesting a bunch of ajax calls inside the 'success' event of one another. I was wondering if someone could guide me in the right direction on how to do something like this? Where one ajax call is dependent on another's return value?
The getLoginAccess() function will be used in many other methods in a similar manner.
If the first one fails i would like to just have it return a 'null' value which i can then take into account before running the second ajax call. Below i demonstrate a psuedo example of what im trying to do.
The method getLoginAccess returns a dictionary of data that is required for the second method createItem to execute. So only if getLoginAccess returns valid data will createItem continue on to call the actual ajax call.
Thank you
function getLoginAccess() {
$.ajax({
url: '.../api/v1/auth/access_token',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/json',
'Connection': 'keep-alive'
},
data: {
grant_type: 'client_credentials',
username: 'johnDoe',
password: '******'
},
success: function (data) {
console.log(JSON.stringify(data));
return data;
},
error: function (data) {
console.log(data);
return null;
}
})
}
function createItem() {
var login = getLoginAccess();
if (login == null) {
return false;
}
$.ajax({
url: '.../api/v1',
method: 'POST',
headers = {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
'access': `${login.access_token}`
};
data: {},
success: function (data) {
console.log(JSON.stringify(data));
},
error: function (data) {
console.log(data);
}
})
}
window.onload = function(){
createItem();
};

If you want to refactor the part where the login is verified we could create an intermediate function .. something like this:
Your login function here
function getLoginAccess(){
// Return login data or null
}
Here we can create an intermediate function to deal with the dependencies of the next execution. If the login returns something other than null, the function passed as a parameter will be executed.
function intermediateFunction(functionName,login){
if(login){
window[functionName]();
}
}
Here are the other functions you have created.
function createItem() {
// Do something
}
function listItem() {
// Do something
}
Here instead of calling the createItem() function you call the intermediary
window.onload = function(){
intermediateFunction(getLoginAccess(), "createItem");
};
So basically you would always call the intermediate function that would check the login before calling a particular function. I believe that this is how I would refactor :)

Related

Can Js and Model.findAll() unable to display data in UI

I have this code where i am trying to retrieve data from model.findall() and display in UI as table
model.js
define(['jquery', 'can'], function ($, can) {
var serviceModel = can.Model.extend({
findAll: function (params,servicename) {
return $.ajax({
type: 'POST',
dataType: 'JSON',
contentType: 'application/json',
url: 'data/+ servicename',
success: function (data) {
console.log("Success ");
},
error: function () {
console.log("Error");
}
});
}
}, {});
return serviceModel;
});
controller.js
serviceModel.findAll(params,"SP_table", function(data) {
if (data.status === "success") {
$('#idtable').dataTable().fnClearTable();
$('#idtable').dataTable().fnAddData(data.result);
}else{
alert("inside alert");
}
});
issue is in serviceModel.findAll() i am unable to get data inside serviceModel.findAll() because data is in the form of stored procedure or macro, which i am getting using "servicename" from function above
please let me know how to resolve this issue.
You can access the raw xhr data from the ajax call and convert it to an appropriate format by overriding the parseModels method:
https://canjs.com/docs/can.Model.parseModels.html
Overwriting parseModels If your service returns data like:
{ thingsToDo: [{name: "dishes", id: 5}] } You will want to overwrite
parseModels to pass the models what it expects like:
Task = can.Model.extend({ parseModels: function(data){ return
data.thingsToDo; } },{}); You could also do this like:
Task = can.Model.extend({ parseModels: "thingsToDo" },{});
can.Model.models passes each instance's data to can.Model.model to
create the individual instances.
In their example above, the response is a nested JSON: in yours, it is your procedure or macro. You have the opportunity here in parseModels to rewrite the response in the appropriate format.

Bypass Ajax request within javascript promise in Unit Testing

I have a function called getStudentData(),returns resolved data.
Inside getStudentData(), I have an Ajax request.
I want to Bypass Ajax request in my unit test case using Mocha , so that when i make a call to getStudentData(), the data should be returned.
Please find the code below:
getStudentData: function() {
return studentData || (studentData = new Promise(function(resolve, reject) {
var request = {
//request data goes here
};
var url = "/student";
$.ajax({
url: url,
type: "POST",
data: JSON.stringify(request),
dataType: "json",
contentType: "application/json",
success: function(response, status, transport) {
//success data goes here
},
error: function(status, textStatus, errorThrown) {
reject(status);
}
});
}).then(function(data) {
return data;
})['catch'](function(error) {
throw error;
}));
}
Please let me know how to Bypass Ajax request By stubbing data using sinon.js .so that when i make a call to getStudentData() , data should be returned.
First of all doing:
then(function(data){ return data; })
Is a no-op. So is:
catch(function(err){ throw err; });
Now, your code uses the explicit construction anti-pattern which is also a shame, it can be minimized to:
getStudentData: function() {
var request = {
//request data goes here
};
var url = "/student";
return studentData ||
(studentData = Promise.resolve($.ajax({
url: url,
type: "POST",
data: JSON.stringify(request),
dataType: "json",
contentType: "application/json" })));
}
Now, that we're over that, let's talk about how you'd stub it. I'd do:
myObject.getStudentData = function() {
return Promise.resolve({}); // resolve with whatever data you want to test
};
Which would let you write tests that look like:
it("does something with data", function() { // note - no `done`
// note the `return` for promises:
return myObj.getStudentData().then(function(data){
// data available here, no ajax request made
});
});
Although in practice you'll test other objects that call that method and not the method itself.

What is callback function in AJAX? How to implement a callback function in PreSaveAction function of SP2013 list NewForm?

I want to store the value of a variable and use it outside the ajax call. But being an asynchronous call it is giving me initial value of that variable. I am implementing my custom code for some validations in PreSaveAction function since I have to do validations on Save button click of SharePoint NewForm,Following is my code,
<script type="text/javascript">
var titleItem;
var flg=0;
var dataFromServer;
function PreSaveAction()
{
titleItem = $("input[title='Title']").val();
$.ajax({
url:"http://sp13dev:4149/Appraisals/_api/web/lists/GetByTitle('SkillMaster')/items?$select=Id,Title&$filter=Title eq '"+titleItem+"'" ,
type: "GET",
async: false,
headers: { "Accept": "application/json; odata=verbose",
"content-type": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val() },
success: function (data) {
if(data.d.results.length>=1)
{
flg=1;
$("#labelTitle").html("Skill already exists. Please enter another name.");
}
else
{
flg=0;
$("#labelTitle").html("");
}
},
error: function (error) {
alert(JSON.stringify(error));
}
});
if(flg==1)
{
// $("#labelTitle").html("Skill already exists. Please enter another name.");
return false;
}
return true;
}
</script>
It seems like you have misplaced your return call. You should have your return placed inside your
if(data.d.results.length>=1)
statement inside the success callback function.

Ajax request, how to call an other function than "success" one's?

I use JQuery Ajax function :
$.ajax({
url: ...,
success: function (){
...
},
...
});
I need to execute some code just before every call of the success function (but after the response has been received).
I suppose that this success function is triggered like an event, so is there a way to make an other function call in place of success one's?
You can use the Global Ajax Event Handlers methods to do this.
Sounds like you might want to use AjaxComplete:
$(document).ajaxComplete(function(){
// do something here when ajax calls complete
});
Be warned -- this will occur for EVERY jQuery ajax call on the page...
You could also call that other function right at the biginning of done:
$.ajax({
url: ...,
done: function (){
someOtherFunction();
},
...
});
This should pretty much accomplish what you described in your question.
Is beforeSend what you are looking for:
$.ajax({
url: "...",
beforeSend: function (x) {
//do something before the the post/get
}
}).done(function (data) {
//done code
});
I succeed in calling an other function just before success one by replacing $.ajax() by a custom function like :
function mYajax(options) {
var temporaryVariable = options.success;
options.success = function () {
console.log('Custom')
if (typeof temporaryVariable === 'function')
temporaryVariable()
};
return $.ajax(options);
}
$('button').click(function () {
mYajax({
url: "/echo/json/",
data: {
foo: "bar"
},
success: function (data, textStatus, jqXHR) {
console.log('succeed action');
},
});
});

synchronize two ajax jquery function

I have two function of jQuery. Both the functions are calling jQuery ajax.
both have property async: false.
In both the function I am redirecting on basis of some ajax response condition.
In the success of first function I am calling the another function and then redirecting to another page. But my first function is not redirecting because my second function is not waiting of the response of the first function.
Hope problem is clear from my question.
my first function is as below
function fnGetCustomer() {
function a(a) {
$("#loading").hide();
//on some condition
//other wise no redirection
self.location = a;
}
var b = $("input#ucLeftPanel_txtMobile").val();
"" != b && ($("#loading").show(), $.ajax({
type: "POST",
url: "Services/GetCustomer.ashx",
data: { "CustMobile": b },
success: a,
async: false,
error: function () {
$("#loading").hide();
}
}));
}
and my second function I am calling the first function
function fnSecond() {
$.ajax({
type: "POST",
url: "some url",
async: false,
data: { "CustMobile": b },
success: function(){
fnGetCustomer();
//if it has all ready redirected then do not redirect
// or redirect to some other place
},
error: function () {
$("#loading").hide();
}
}));
}
I am using my first function all ready. So I don't want to change my first function.
A set up like this should work;
$.ajax({
data: foo,
url: bar
}).done(function(response) {
if (response == "redirect") {
// redirect to some page
} else {
$.ajax({
data: foo,
url: bar
}).done(function(response2) {
if (response2 == "redirect") {
// redirect to some other page
} else {
// do something else
}
});
}
});​
I've not tested doing something like this, but that's roughly how I'd start off
If you don't need the result of the first AJAX call to be able to send the second you could add a counter to keep track of the calls. Since you can send both calls at the same time it'll be a lot more responsive.
var requestsLeft = 2;
$.ajax({
url: "Firsturl.ashx",
success: successFunction
});
$.ajax({
url: "Secondurl.ashx",
success: successFunction
});
function successFunction()
{
requestsLeft--;
if (requestsLeft == 0)
doRedirectOrWhatever();
}
If you absolutely need to do them in order you could do something like this. My example expects a json response but that's no requirement for this approach to work.
var ajaxurls = ["Firsturl.ashx", "Secondurl.ashx"]
function doAjax()
{
$.ajax({
url: ajaxurls.shift(), // Get next url
dataType: 'json',
success: function(result)
{
if (result.redirectUrl) // or whatever requirement you set
/* redirect code goes here */
else if (ajaxurls.length>0) // If there are urls left, run next request
doAjax();
}
});
}
doAjax();

Resources