I'm trying to fetch some urls from the back-end and assign data.Results in window.__env.{variable} so I can use it anywhere in the application.
I have this code
(function(window){
window.__env = window.__env || {};
$.ajax({
url: './assets/js/config/config.json',
method: 'GET',
success: function (data) {
let baseUrl = data.BaseApiUrl;
workflowDefinition(baseUrl);
}
})
function workflowDefinition(baseUrl) {
$.ajax({
url: baseUrl + 'api/Management/Configurations?name=SaveWorkflowDefinition&name=WorkflowDefinition',
method: 'GET',
success: function (data) {
if (data && data.Results && data.Results[0] && data.Results[0].Value) {
window.__env.saveWorkflowDefinition = data.Results[0].Value;
console.log(window.__env.saveWorkflowDefinition);
}
if (data && data.Results && data.Results[1].Value) {
window.__env.getWorkflowDefinition = data.Results[1].Value;
}
},
error: function (error) {
var errorMessage = "Failed to contact Workflow Server, please contact your IT administrator";
alert(errorMessage);
}
})
}
}(this))
I can see that the console.log is printing when this loads it gives me the right URL, then I tried passing window.__env.saveWorkflowDefinition to say another file xfunction.js where I want to use window.__env but it gives me undefined.
However if I pass it like this without ajax call, it works fine.
(function(window){
window.__env = window.__env || {};
window.__env.saveWorkflowDefinition= 'www.mybaseurl.com/api/Management/';
})
Can someone point out why its returning undefined when I pass it to xfunction.js when doing an ajax call?
Since your Ajax calls will only provide the response asynchronously, you cannot expect to have the response in the same synchronous execution context.
One idea to resolve this, is to abandon the idea to store the response in a global (window) property, but to store instead a promise, which you do get synchronously.
The code could look like this:
window.promiseWorkFlowDefinition = $.ajax({
url: './assets/js/config/config.json',
method: 'GET',
}).then(function (data) {
return $.ajax({
url: data.BaseApiUrl + 'api/Management/Configurations?'
+ 'name=SaveWorkflowDefinition&name=WorkflowDefinition',
method: 'GET',
})
}).then(function (data) {
return data && data.Results && (data.Results[0] && data.Results[0].Value
|| data.Results[1] && data.Results[1].Value)
|| ('No Results[0 or 1].Value found in:\n' + JSON.stringify(data));
}, function (error) {
var errorMessage =
"Failed to contact Workflow Server, please contact your IT administrator";
alert(errorMessage);
});
// Other file:
window.promiseWorkFlowDefinition.then(function(saveWorkflowDefinition) {
// Use saveWorkflowDefinition here. This is called asynchronously.
// ...
});
Related
I have a function get_dish() which makes an AJAX-request to my back-end to retrieve a Dish-object with the requested ID.
function get_dish(id) {
let url = "/api/dishes/" + id;
let r;
$.ajax({
type: 'GET',
url: url,
async: false,
success: function(response) {
r = response;
}
});
return r;
}
The problem I had is that when get_dish() is called a lot my page would slow down because of all the HTTP-requests.
So I came up with the idea to cache the objects I request in localStorage. So when get_dish() is called, the returned Dish-object gets stored in localStorage. To achieve this I made the following caching-system:
// system to cache objects requested from API.
class ApiCache {
constructor(dishes) {
this.dishes = dishes;
}
}
// intialize ApiCache
if (localStorage.getItem("apicache") == null) {
localStorage.setItem("apicache", JSON.stringify(new ApiCache([])));
}
function apicache_add_dish(dish) {
let apicache = JSON.parse(localStorage.getItem("apicache"));
if (apicache_get_dish(dish.id) != null) {
return;
}
apicache.dishes.push(dish);
localStorage.setItem("apicache", JSON.stringify(apicache));
}
function apicache_get_dish(id) {
let apicache = JSON.parse(localStorage.getItem("apicache"));
return apicache.dishes.find(dish => dish.id == id);
}
The updated get_dish() looks like this:
function get_dish(id) {
if (apicache_get_dish(id) != null) {
return apicache_get_dish(id);
}
let url = "/api/dishes/" + id;
let r;
$.ajax({
type: 'GET',
url: url,
async: false,
success: function(response) {
r = response;
if (apicache_get_dish(id) == null) {
return apicache_add_dish(r);
}
}
});
return r;
}
This way, when the same dish is requested multiple times no HTTP-requests needs to be made, but it can just be retrieved from the cache instead. I'd but an expiration on the localStorage to belittle the chance of data inconsistency.
Is this a good idea? What are the pro's and cons? Can this be improved?
I am trying to return an object from a $rootScope function called retrieveUser() in AngularJS. The object is returned. I have run console.log() on the response of the function ran when $http is successful. Here is my $rootScope function:
$rootScope.retrieveUser = function() {
var apiUrl = "http://104.251.218.29:8080";
if($cookies.get('tundraSessionString')) {
var cookie = $cookies.get('tundraSessionString');
$http({
method: "POST",
url: apiUrl + "/api/master/v1/auth/checkauth",
data: "sessionString=" + cookie,
headers: {
'Content-Type' : 'application/x-www-form-urlencoded;',
'Cache-Control': 'no-cache'
}
}).then(function mySuccess(response) {
if(response.data.event == "error") {
window.location = "/auth/logout";
} else {
return response.data;
}
})
} else {
window.location = "/auth/login";
}
};
With this method, I access it in my controller such as this (and console.log() just to test my work):
vm.user = $rootScope.retrieveUser();
console.log($rootScope.retrieveUser());
But, I have yet to get this to work. I have tried specifying specific objects in an array in my $rootScope function. I know it runs, because I have the $rootScope consoling something when it is run, and it shows a console.log() of the response of the $http request. It looks like this:
Object {event: "success", table: Object}
event:"success"
table:Object
__proto__:Object
Yet, when I console.log() the vm.user with the function $rootScope.retrieveUser(), even though the function is supposed to be returning the object, I simply receive "undefined".
I have been banging my head on this for days, read some articles on functions/objects and I still cannot figure this out. We're two days in.
try this:
if($cookies.get('tundraSessionString')) {
var cookie = $cookies.get('tundraSessionString');
//return a promise
return $http({
method: "POST",
url: apiUrl + "/api/master/v1/auth/checkauth",
data: "sessionString=" + cookie,
headers: {
'Content-Type' : 'application/x-www-form-urlencoded;',
'Cache-Control': 'no-cache'
}
}).then(function mySuccess(response) {
if(response.data.event == "error") {
window.location = "/auth/logout";
}
else {
return response.data;
}
})
}
else {
window.location = "/auth/login";
}
and
$rootScope.retrieveUser().then(function(user){vm.user = user;})
What you are returning from retrieveUser when your cookie is set is what $http returns, which is a promise. Try this:
$rootScope.retrieveUser().then(function(user){vm.user = user;})
retrieveUser fn doesn't return your data :)
$http is asynchronous function and you should read about promises
function handleUser(user){
//do something
}
function retrieveUser(callback){
$http({...}).then(function(response){
callback(response.data.user);
});
}
//how to use it:
retrieveUser(handleUser);
but first of all you may need a service for getting some data instead of using $rootScope
and secondly you can pass a user in your template in script tag
then you don't need another http request and user will be globaly available
<script>var user=<?php echo json_encode($user);?></script>
I'm currently dealing with refactoring my code, and trying to automate AJAX requests as follows:
The goal is to have a context-independent function to launch AJAX requests. The data gathered is handled differently based on the context.
This is my function:
function ajaxParameter(routeName, method, array, callback){
//Ajax request on silex route
var URL = routeName;
$.ajax({
type: method,
url: URL,
beforeSend: function(){
DOM.spinner.fadeIn('fast');
},
})
.done(function(response) {
DOM.spinner.fadeOut('fast');
callback(response);
})
.fail(function(error){
var response = [];
response.status = 0;
response.message = "Request failed, error : "+error;
callback(response);
})
}
My problem essentially comes from the fact that my callback function is not defined.
I would like to call the function as such (example)
ajaxParameter(URL_base, 'POST', dataBase, function(response){
if(response.status == 1 ){
console.log('Request succeeded');
}
showMessage(response);
});
I thought of returning response to a variable and deal with it later, but if the request fails or is slow, this won't work (because response will not have been set).
That version would allow me to benefit the .done() and .fail().
EDIT : So there is no mistake, I changed my code a bit. The goal is to be able to deal with a callback function used in both .done() and .fail() context (two separate functions would also work in my case though).
As far as I can see there really is nothing wrong with your script. I've neatened it up a bit here, but it's essentially what you had before:
function ajaxParameter (url, method, data, callback) {
$.ajax({
type: method,
url: url,
data: data,
beforeSend: function(){
DOM.spinner.fadeIn('fast');
}
})
.done( function (response) {
DOM.spinner.fadeOut('fast');
if (callback)
callback(response);
})
.fail( function (error){
var response = [];
response.status = 0;
response.message = "Request failed, error : " + error;
if (callback)
callback(response);
});
}
And now let's go and test it here on JSFiddle.
As you can see (using the JSFiddle AJAX API), it works. So the issue is probably with something else in your script. Are you sure the script you've posted here is the same one you are using in your development environment?
In regards to your error; be absolutely sure that you are passing in the right arguments in the right order to your ajaxParameter function. Here's what I am passing in the fiddle:
the url endpoint (e.g http://example.com/)
the method (e.g 'post')
some data (e.g {foo:'bar'})
the callback (e.g function(response){ };)
Do you mean something like this, passing the success and fail callbacks:
function ajaxParameter(routeName, method, array, success, failure) {
//Ajax request on silex route
var URL = routeName;
$.ajax({
type: method,
url: URL,
beforeSend: function () {
DOM.spinner.fadeIn('fast');
}
}).done(function (response) {
DOM.spinner.fadeOut('fast');
success(response);
}).fail(function (error) {
var response = [];
response.status = 0;
response.message = "Request failed, error : " + error;
failure(response);
})
}
Called like:
ajaxParameter(
URL_base,
'POST',
dataBase,
function(response){
//success function
},
function(response){
// fail function
}
);
Hi;
when i'm using from jQuery ajax, the page getting to freeze until request end.
this is my JavaScript code:
function GetAboutContent(ID, from) {
var About = null;
if (from != true)
from = false;
$.ajax({
type: "POST",
url: "./ContentLoader.asmx/GetAboutContent",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify({ 'ID': ID, 'from': from }),
async: true,
success: function (msg) {
var Result = msg.d.Result;
if (Result == 'session') {
warning('Your session has expired, please login again!');
setTimeout(function () {
window.location.href = "Login.aspx";
}, 4000);
return;
}
if (Result == 'failed' || Result == false) {
About = false;
return;
}
About = JSON.parse(msg.d.About)[0];
}
});
return About;
}
and this is my WebService
[WebMethod(EnableSession = true)]
public object GetAboutContent(int ID, bool from = false)
{
try
{
if (HttpContext.Current.Session["MahdParent"] != null ||
HttpContext.Current.Session["MahdTeacher"] != null ||
from)
{
functions = new GlobalFunctions();
DataTable queryResult = new DataTable();
queryResult = functions.DoReaderTextCommand("SELECT Field FROM TT WHERE ID = " + ID);
if (queryResult.Rows.Count != 0)
return new { Result = true, About = JsonConvert.SerializeObject(queryResult.Rows[0].Table) };
else
return new { Result = false };
}
else
return new { Result = "session" };
}
catch (Exception ex)
{
return new { Result = "failed", Message = ex.Message };
}
}
How can i solve that problem?
please help me
In the last line you try to return About. That cannot work due to the asynchronous nature of an AJAX request. The point at which you state return About doesn't exist any more when the success function of your AJAX request runs.
I assume you try do do somehting like this:
$('div#content').html(GetAboutContent());
In a procedural lantuage like PHP or Perl this works fine, yet JavaScript functions in a very different way. To make something like this work you'd do something like this:
$.ajax({
type: "post",
url: "./ContentLoader.asmx/GetAboutContent",
dataType: "json",
data: {
'ID': ID,
'from': from
},
success: function(result) {
$('div#content').html(result)
}
});
The difference between the two bits of code is that the first would expect JavaScript to know the value at the time you request it. However, your function GetAboutContent() doesn't have instant access to these data. Instead it fires up an AJAX request and ends right after that with the request still in progress for an unknown amount of time.
Once the request finishes successfully the data is available to JavaScript. and you can work with it in the callback function defined for success. By then the request has absolutely no connection to the function that started it. That's why it's asynchronous.
Below you will see some code to set the currently logged in user for an extjs 4 application. If I have the alert uncommented, the code seems to wait until the alert is accepted before the code continues (it seems). That allows enough time for the asynchronous call to complete with a success. If I comment out the alert, the variable "employeeFilter" never gets set because the AJAX call didn't come back in time. In which case, it sets the "employeeFilter" to null instead. How can I fix this so it waits until the AJAX response comes back in success?
var loggedInUserId = null;
Ext.Ajax.request({
url: '/Controls/UserList/UserService.asmx/GetLoggedInUserId',
method: 'POST',
jsonData: { 'x': 'x' },
success: function (response, opt) {
loggedInUserId = Ext.decode(response.responseText).d;
},
failure: function (response) {
}
});
//alert(loggedInUserId);
var employeeFilter = loggedInUserId;
var projectFilter = '-1';
I would have done this.
var employeeFilter;
Ext.Ajax.request({
url: '/Controls/UserList/UserService.asmx/GetLoggedInUserId',
method: 'POST',
jsonData: { 'x': 'x' },
success: function (response, opt) {
employeeFilter = Ext.decode(response.responseText).d;
//Do here whatever you need to do once the employeeFilter is set. probably call a function and pass the employee filter as parameter.
},
failure: function (response) {
}
});
var projectFilter = '-1';