I have the following javascript code:
function initSite(){
var site;
$.getJSON(www+'init/initSite', function(data) { site = data; });
}
$(document).ready(function(){
var site = initSite();
console.log(site);
}
which returns undefined... how can i store the json object that i recieve in the site variable so i can use it later?
EDIT:
This seem to work but im not sure if its correct to use this solution
var site = null;
$.ajax({
url: www+"init/initSite",
async: false,
dataType: 'json',
success: function (data) {
site = data;
}
});
console.log(site);
of course you got undefined because your function doesn't return anything and the ajax call is also asynchronous, so you have to wait the server response. Since $.ajax (and shortcuts) returns a promise you can do this task using deferred
function initSite(){
return $.getJSON(www+'init/initSite');
}
$(document).ready(function(){
$.when(initSite()).done(function(data) {
/* continue here the code execution, e.g. call another function */
doAllTheRemainingWorkWith(data)
});
}
as you can see this code is short and easy to read
function initSite(onSuccess){
$.getJSON(www+'init/initSite', onSuccess);
}
$(document).ready(function(){
initSite(function(data){
var site = data;
// initialize your code.
});
}
The problem is just a miss concept:
getJSON is an async call, and the site = data; will only happen way after the DOM is ready.
in order for you to make everything work the way it should, your initialization needs to start from your async call result and never before, for example:
// no need to wait for DOM ready to call `initSite`
initSite();
function initSite() {
$.getJSON(www+'init/initSite', function(data) {
initialization(data);
});
}
function initialization(site) {
// initialize all the things that need to be done
console.log(site);
}
$(document).ready(function(){
// do other stuff, for example show a loading message/image
}
Related
I wish to refresh the page after values have been saved to a database, using js promises.
My code is wrapped inside a jQuery event listener:
$("img[class=okButton]").click(function(){
var field_userid = $(this).attr("id");
doThisFirst();
// then make a promise
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
wait(500).then(() => writeNewRoom(field_userid)); // function to write to database
refreshPage(); // after write has finished
});
///////////////////
function writeNewRoom(field_userid)){
// ajax to do something;
}
///////////////////
function refreshPage(){
if(window.confirm("Click to refresh")){location = location}
}
The intended behaviour is to process data first, then finish "doing something" in the writeNewRoom() function before refreshing the page in the refreshPage() function.
What is actually happening is that the first doThisFirst() function is processed correctly, but then the window.confirm box in the third function, pops up BEFORE the writeNewRoom function has run.
I've never used promises before, so can anyone help figure out what went wrong? I took the basic syntax from the mozilla website: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises
Any help is much appreciated.
In your case, you would want to put a call back in your writeNewRoom() method.
For example, you call whatever you need to do on the .click() function and put a .done() method when your ajax call for writing to the database is done.
$("img[class=okButton]").click(function(){
var field_userid = $(this).attr("id");
doThisFirst();
// Remove the Promise
writeNewRoom(field_userid); // function to write to database
});
function writeNewRoom(field_userId) {
$.ajax({
url: "/someurl",
method: "method",
data: {
a: field_userId
}
}).done(function(data) {
console.log('success', data)
refreshPage(); // This is where you refresh the page.
}).fail(function(xhr) {
console.log('error', xhr);
});
}
If your // ajax to do something; returns a promise (jQuery.ajax() does) you can do it like this:
wait(500).then(() => writeNewRoom(field_userid))
.then(() => refreshPage());
There's also one extra parenthesis here function writeNewRoom(field_userid))
if the writeNewRoom(field_userid) is doing an ajax call, you put the refreshPage()-function into the callback of the ajax call, so it is executed AFTER the ajax has finished, e.g:
function writeNewRoom(field_userid)){
$.ajax({
url: "someUrl",
type: 'GET',
success: (result) => {
refreshPage() //when ajax has succeded, refresh page
},
error: (err) => {
//do something else
}
});
}
In my usecase, I am using both external and inline javascript contents. I have the following structure.
app/
header.html
home.html
config-load.js
footer.html
home.html includes header.html and footer.html. header.html file includes config-load.js.
config-load.js makes an ajax call to get the configs based on the stage from golang backend. This may have few milliseconds delay.
There are few inline scripts in home.html which uses the configs collected by config-load.js ajax call.
So config-load.js ajax call must be completed before inline scripts are loaded. But it is loading in the other way around.
I tried to use a while loop to delay the load time for the inline scripts as below,
while(configReceived == false)
{
setTimeout(function(){
console.log("waiting for config");
}, 2000);
}
if(configReceived)
{
//process configs
}
But this blocks the thread. The page is stuck in the while loop. Is there any other way to achieve this?
EDIT 1 :
Here is the inline script content,
<script type="text/javascript">
window.onload = function() {
time = new Date($.now());
var tagsArray = ["C", "C++", "Go", "Ruby"];
//var tagsArray = [];
requestJSON = '{"Method":"GET","AppName":"Web-app","ServiceURL":"'+endpoints.Tags.HTTPEndpoint.URL+'","Properties":null,"Object":"","Timestamp":"'+time+'"}'
$.ajax({
type: "GET",
url: endpoints.Tags.HTTPEndpoint.URL,
data: requestJSON,
processData: false,
contentType: "application/json;",
dataType: "json",
async: false,
success: function(data){
console.log("tags retrieved successfully info updated successfully")
console.log("Tags ", data.Object)
tagsArray = data.Object
},
failure: function(errMsg) {
console.log("Error occured in getting tags ", errMsg)
}
});
$("#myTags").tagit();
$("#tags").tagit({
fieldName: "tagsName", // The name of the hidden input field
availableTags: tagsArray,
allowSpaces:true,
caseSensitive:false,
removeConfirmation:true,
placeholderText:"Tags",
tagLimit: 5,
allowDuplicates: false,
singleField: true, // Use a hidden input element with the fieldName name
singleFieldDelimiter: ',', // Optional, default value is same.
onlyAvailableTags: false
});
}
</script>
And my config-load.js looks like below,
//////////////////////////////////////////////////////////
// code block to get the service endpoints by stage starts
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
endpoints = JSON.parse(xhr.responseText);
console.log("server endpoints be ", endpoints);
configReceived = true;
}
}
xhr.open("GET", "/config", true);
try {
xhr.send();
} catch (err) {
// handle error
console.log("Error occured in getting the service endpoints. This may break all ajax services");
}
// code block to get the service endpoints by stage ends
////////////////////////////////////////////////////////
I am trying for last 3 days but no luck.
"while loop" is synchronous, which means it will block the thread and makes whole application stuck.
Javascript async scripts's execution order is not guaranteed, so you should use the "callback" or in ES6 you can use promise, ES7 you can use async, await.
Anyway the better way is wrap your config-load.js javascript code in a function, if you use Jquery's ajax api, the code may looks like this:
function loadConfigAjax(callback){
$.ajax({url: "http://myconfig", success: function(config){
callback(config)
}});
}
And in your inline javascript may looks like this
<script type="text/javascript">
window.onload = function() {
var configReceived = function(config){
//process configs
};
// pass the configReceived as callback
// so that configReceived function will always be invoked after config received
loadConfigAjax(configReceived);
}
</script>
Be aware that javascript is asynchronous and you don't have full control over the loading sequences of the scripts, unless you are not using the async await new javascript feature or promises. But in your case is not really needed for these.
First thing you need to do is to include the config-load.js in the head section, right on the top, this way you have some guarantee that the file is loaded before the DOM is getting populated.
Another thing is to use the window.onload function inside the inline scripts, to force the browser to parse the scripts only after all the DOM structure has been constructed and fully populated.
So inside your html section wrap your function into the window.onload function callback:
<script type="text/javascript">
window.onload = function() {
while(configReceived == false)
{
setTimeout(function(){
console.log("waiting for config");
}, 2000);
}
if(configReceived)
{
//process configs
}
}
</script>
EDIT:
There are quite a few errors in your approach. First and foremost there is no need to call the ajax requests in two separate scripts. Using the above mentioned promise technique you can chain the responses. Here is a short example of how the jquery promises are working:
function first() {
return $.ajax(...);
}
function second(data, textStatus, jqXHR) {
return $.ajax(...);
}
function third(data, textStatus, jqXHR) {
return $.ajax(...);
}
function main() {
first().then(second).then(third);
}
Remember: a call in the chain group return the response. Which means that you can delegate the response to the next chain, which means that when the request has been resolved you can pass through the result to the next call.
Applying to your example when you receive the response by calling the endpoints service, you can pass the result as parameter to the next call, and this will be accessed only when the response from the first call will be resolved.
Check this fiddle as an example.
Applying this technique it's not needed needed anymore to check configReceived = true;.
Another thing you have to make sure is that jQuery is included before you are trying to call jQuery.ajax.
Here are some references about promises:
http://www.danieldemmel.me/blog/2013/03/22/an-introduction-to-jquery-deferred-slash-promise/
http://www.bitstorm.org/weblog/2012-1/Deferred_and_promise_in_jQuery.html
https://davidwalsh.name/write-javascript-promises
I am using below code
var lockonscreens = 1;
jQuery(document).ready(function(e) {
var noOfSelection = 0;
if(lockonscreens == 0){
// some stuff
}
if(lockonscreens == 1){
// some stuff
}
});
function ajaxcall(){
jQuery.ajax({
url:
type:
data:
async: false,
success: function(data){
lockonscreens = data;
}
});
}
jQuery("#").click(function(){
ajaxcall();
});
I am using above code to get some data through ajax and set it to variable and depending on that variable a click event code may happen.
But on ajax call the global variable value doesn't get changed.
It remains the same even if the data changes in ajax.
Can anyone let me know what is the issue and how to correct it?
Remember that ajax is asynchronous, so if you call ajaxCall() and next an other function, ajax start the call to server and the function end.
When the server respond, the code after success: is executed.
Make sure you call the function in the success: function
I want to do something like this:
$.ajax({
url: SOMEWHERE,
...
success: function(data){
// do sth...
var new_url = data.url;
$.ajax({
url: new_url,
success: function(data){
var another_url = data.url;
// ajax call rely on the result of previous one
$.ajax({
// do sth
})
}
})
},
fail: function(){
// do sth...
// ajax call too
$.ajax({
// config
})
}
})
the code looks awful for me.
I wonder how to make it looks pretty. Some best practice?
I would consider breaking it up, maybe something like this.
function initialSuccessHandler(data) {
$.ajax({url:data.url, success:secondarySuccessHandler});
}
function secondarySuccessHandler(data) {
//do stuff
}
function initialFailHandler() {
$.ajax({...});
}
$.ajax({url:"whatever.com", success:initialSuccessHandler, fail: initialFailHandler});
There's not a whole lot you can probably do about it other than if the success function are similar (just need different URL's to new AJAX calls for example) you might be able to define a common function to call recursively, like this:
function do_something(data) {
// some logic
$.ajax({
url: data.url,
success: do_something(data);
fail: function (){
// handle failure
}
});
}
Use $.post instead of $.ajax that's lot easier and clean
$.post('yourAjaxUrl.com/index.html',(newVal:'val'), function(data) {
$.post('yourSecondAjaxUrl.com/index.html',{newVal1:data}, function(data) {
//do something
});
});
Or if you want to use GET request use like this.
$.get('yourAjaxUrl.com/index.html',(newVal:'val'), function(data) {
$.get('yourSecondAjaxUrl.com/index.html',{newVal1:data}, function(data) {
//do something
});
});
Other answers are mostly fine too as using functions in a lot of case will definitely help your code. The problem of your function is that it's doing to much things all in once. Decreasing the complexity of the function will help a LOT (separating different action in different functions).
There's some good training videos of Bocoup here which can help you decrease a function complexity: http://training.bocoup.com/screencasts/
Although, a basic answer to the callback inferno:
You could use jquery Deffered who do a good job in certain case by preventing the "indentation pyramid of doom". (But won't decrease the complexity of your function)
$.ajax({
url: SOMEWHERE
})
.pipe(function() {
// First success callback
return $.ajax({
url: new_url
});
}, function() {
// First error callback
$.ajax({
// config
});
// we ain't returning anything so this end here.
})
.done(function( data ) {
// Second success callback
var another_url = data.url;
// ajax call rely on the result of previous one
$.ajax({
// do sth
})
});
Deferred can fit in a whole lot more of context, and learning about them is really useful. That's only the basic idea behind them.
Hope this help!
I'm no professional in JavaScript and I've seen searching a long time for this on the internet.
I'm having a problem getting a variable from another function. My code is looking like this:
var variabeltje;
$.post('js/ajax/handle_time.php', {'time': $(this).find('input').val()},
function(data) {
alert(data);
variabeltje=data;
}
);
alert(window.variabeltje);
The variable variabeltje must get the information from data. When I put the alert below variabeltje=data it's working, but I need the data variable after the function.
Edit:
I have changed it to what people said, I now have this:
var XHR = $.post('js/ajax/handle_time.php', {time: $(this).find('input').val()});
XHR.done(function(data) {
console.log(data);
getData(data);
});
function getData(data) {
if(data == 'true') {
alert(data);
$(this).unbind('keypress');
$(this).html($(this).find('input').val());
}
}
But now the $(this) isn't passing into the function. How can I solve this?
As it's asynchronous the data will only be available after the ajax call is completed, so you'll have to modify your code to work with that and wait until after the ajax is done to do your stuff:
var XHR = $.post('js/ajax/handle_time.php', {time: $(this).find('input').val()});
XHR.done(function(data) {
console.log(data);
});
or in other function:
function XHR(time){
return $.post('js/ajax/handle_time.php', {time: time});
}
function doStuff(element) {
XHR($(element).find('input').val()).done(function(data) {
console.log(data);
});
}
EDIT:
based on your edit, it looks like it's a scoping issue:
var self = this,
XHR = $.post('js/ajax/handle_time.php', {time: $(self).find('input').val()});
XHR.done(function(data) {
console.log(data);
getData(data);
});
function getData(data) {
if(data == 'true') { //normally you'd try to pass true as a boolean, not string
alert(data);
$(self).unbind('keypress').html($(self).find('input').val());
}
}
This is because the $.post method runs asynchronously.
Please take a look at this question on SO.
Edit: You can change your code and put the part after post method inside the body of the anonymous function triggered on success. As follows:
$.post('js/ajax/handle_time.php', {'time': $(this).find('input').val()},
function(data) {
alert(data);
variabeltje=data;
alert(window.variabeltje); // or whatever function you need to call, call it here...
}
);
The problem is that post method is executed asynchronously. This is, a post is sent to the server but execution flow continues so your alert is trying to access a value that wasn't set since post haven't returned yet.
You could use ajax method if you need a synchronic execution.