I'm new in javascript and jQuery.
I'm using ajax calls to get data from my server. The fact is, I'm losing my javascript variables after the call ..
Here is what I did : the variable is define outside any function and treat in an other function.
var a = 0;
function myfunction(url){
$.ajax({
url: url,
timeout: 20000,
success: function(data){
// Do some stuff
// The a variable is now undefined
},
error: function(){
// Do some stuff
}
});
}
Everything is working fine, the only thing is that I need to keep my variables ... but it looks like it's gone ..
Does anyone know why?
Thanks
You say you're using your variable in another function (but don't show us that function). However, that function is probably running before your AJAX call is complete. This is what "asynchronous" means -- they don't take place at the same time.
To fix this, add some more code inside your success callback, where it will run only after the a variable is changed.
This works and the url does stay in scope. What you should check is if you are getting an error - this will prevent success from running (toss an alert("error"); or something similar in there to test).
I use Firebug in FireFox to help me out.
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<script type="text/javascript">
var a = 0;
function doSomething (url){
$.ajax({
url: url,
timeout: 20000,
success: function(data){
alert(a);
},
error: function(){
// Do some stuff
}
});
}
</script>
Do it
Related
After my previous question, I come up to the following working code that is intended to refresh the DOM periodically by replacing the <div id="test_css_id">...</div> itself. The behavior of both AJAX requests present in the below code is to reload the same code itself.
<div id="test_css_id">
<a id="link_css_id" href="test_url.html">LINK</a>
<script type="text/javascript">
var refreshTimer;
$('#link_css_id').click(function(event) {
event.preventDefault();
$.ajax({
url: $(this).attr('href'),
type: 'PUT',
success: function(data) {
clearInterval(refreshTimer);
$('#test_css_id').replaceWith(data); // Replaces all code including JavaScript with the response data (note: the response data is exactly the same as the code shown here).
}
});
});
$(document).ready(function() {
function refreshFunction(){
$.ajax({
url: 'test_url.html',
type: 'GET',
success: function(data) {
clearInterval(refreshTimer);
$('#test_css_id').replaceWith(data); // Replaces all code including JavaScript with the response data (note: the response data is exactly the same as the code shown here).
}
});
}
refreshTimer = setInterval(refreshFunction, 1000);
});
</script>
</div>
However, as said by the author of the accepted answer, "there are other ways you can do it [..] one way is to wrap all of that code into a module". I am not expert in JavaScript but I would like to understand and learn it a little more.
How can I wrap all of that code into a module in order to avoid using global variables?
Your current code looks like this:
var refreshTimer; //a global variable
$(...).click(...);
To make refreshTimer not global, you need to put it inside a function:
function main(){
var refresherTimer; //this variable is now local to "main"
$(...).click(...);
}
main();
However, doing it this way won't solve the problem completely. While we did get rid of the global variables, we added a new one - the "main" function itself.
The final trick is to turn the "main" function into an anonymous function and invoke it directly. This is the famous "module pattern":
(function(){
var refreshTimer; //local variable to that anonymous function
$(...).click(...);
}()); //and here we call the function to run the code inside it.
The extra parenthesis around everything are important. If you do just function(){}() instead of (function(){}()) then you will get a syntax error.
Here's a nice description of the module pattern in JavaScript.
So I have script that is for a Bingo game. I'm having a problem running one of my functions inside another function. The idea was to have my checkBingo() function be defined outside of a .click() function. There's some ajax at work, so I'm not sure if that's coming into play here too. Looks something like:
$(document).ready(function(){
function checkBingo() {
$.ajax({
url: '/check-bingo',
type: 'GET',
success: function(data){
return data;
}
}):
}
$('#div').click(function() {
// Some stuff gets done here
$.ajax({
url: '/tile',
type: 'GET',
success: function(data){
// Does some stuff with data, then needs to check if there's a bingo.
var isBingo = checkBingo();
if (isBingo == 'something') {
// Displays something specific on the page.
} else {
// Displays other things on the page.
}
}
}):
});
Where I'm getting hung up, is that isBingo is never getting assigned the returned info. I thought it might have been because the query wasn't running fast enough, so I've tried sticking the variable in a loop until it got something assigned to it and then the console told me that my checkBingo() inside the .click function wasn't defined. I'm not sure if it's just a stupid syntax error on my part or if what I'm doing isn't possible.
Can someone verify that this is indeed possible and that I've probably just got to scour it for the syntax error?
Because this line:
var isBingo = checkBingo();
...is calling an function (checkBingo) which makes an asynchronous call and does not return anything, isBingo will be undefined.
One way to approach this would be to pass a callback function to checkBingo since JavaScript allows functions to be passed around like data, and the function will be called by jQuery when the data is obtained from the server:
function checkBingo(callback) {
$.ajax({
url: '/check-bingo',
type: 'GET',
success: function(data){
callback(data);
}
// or you could just do:
// success: callback,
});
}
// ....
success: function(data){
checkBingo(function (isBingo) {
if (isBingo == 'something') {
// Displays something specific on the page.
} else {
// Displays other things on the page.
}
});
Another approach, which would allow you to continue using your synchronous style (i.e., where checkBingo could return something and you could immediately use it) even though the code is not executed synchronously is by taking advantage of the fact that the later versions of jQuery's Ajax API return a promise object which allows this style of coding:
$(document).ready(function(){
function checkBingo() {
return $.ajax({
url: '/check-bingo.txt',
type: 'GET'
});
}
$('#div').click(function() {
// Some stuff gets done here
$.ajax({
url: '/tile.txt',
type: 'GET',
success: function(data){
var checkingBingo = checkBingo();
checkingBingo.done(function (isBingo) {
if (isBingo == 'something') {
alert('a');
// Displays something specific on the page.
} else {
alert('b');
// Displays other things on the page.
}
});
}
});
});
});
Besides the need to convert a couple of your colons into semi-colons, and add the jQuery $ in front of your "#div" code, two other aspects to note:
I added the ".txt" extension to the Ajax calls in case the extension was merely hidden on your system.
The code $('#div') presumes that there is an element on your page with the ID set to "div". If you want all div elements to be clickable, you would simply need to do $('div').
Sorry if this is a duplicate but I couldn't find any satisfying answers in the previous posts.
$(function() {
$.ajax({
url: 'ajax/test.html',
success: function(data) {
// Data received here
}
});
});
[or]
someFunction() {
return $.ajax({
// Call and receive data
});
}
var myVariable;
someFunction().done(function(data) {
myVariable = data;
// Do stuff with myVariable
});
The above code works just fine. However, this ajax request is made on page load and I want to process this data later on. I know I can include the processing logic inside the callback but I don't want to do that. Assigning the response to a global variable is not working either because of the asynchronous nature of the call.
In both the above ways, the 'data' is confined either to the success callback or the done callback and I want to access it outside of these if possible. This was previously possible with jQuery 'async:false' flag but this is deprecated in jQuery 1.8.
Any suggestions are appreciated. Thank you.
You can "outsource" the callback to a normal function, so you can put it somewhere, you like it:
$(function() {
$.ajax({
url: 'ajax/test.html',
success: yourOwnCallback
});
});
somehwere else you can define your callback
function yourOwnCallback(data) {
// Data received and processed here
}
this is even possible with object methods as well
This solution might not be idea but I hope it helps.
Set the variable upon callback.
Wherever you need to process the data, check if variable is set and if not wait somehow.
Try:
$(document).ready(function(){
var myVar = false;
$.ajax({
url: 'ajax/test.html',
success: function(data) {
myVar=data;
}
});
someFunction(){ //this is invoked when you need processing
while(myVar==false){}
... do some other stuff ..
}
});
Or
someFunction(){
if(myVar==false){
setTimeout(someFunction(),100); //try again in 100ms
return;
}
.. do some other stuff ..
}
I'm sure the solution is staring me right in the eyes, but I just cannot see it. I am trying to load an object from an outside file source. I've tried it several which ways using jQuery's built in methods, but keep returning undefined. Is my issue the scope? I need partnerData right where it is because of other dependent methods in my script. I don't want to operate the rest of my site's functions from within the $.get callback. Any help is greatly appreciated, here's the code:
$(function() {
var partnerData;
$.get('data/partners.json', function(file) {
partnerData = $.parseJSON(file);
});
console.log(partnerData); /* returns undefined instead of object */
});
EDIT:
Thanks for all the feedback everyone. This is the solution I went with:
var partnerData;
$.ajax({
url: 'data/partners.json',
dataType: 'json',
async: false,
success: function(data) {
partnerData = data;
}
});
The reason why you're seeing undefined is because ajax requests are asynchronous by default. This means your get method gets invoked and the code flow moves down to the next statement while the request executes in the background. Your callback function is later invoked when the request completes.
Using callback functions is a common pattern used in situations like this. But you seem to be saying you don't want to do or can't do that. In that case, you could use async: false which would force the request to be synchronous. Keep in mind however, that your code will be blocked on the request and if it's a long-lived request, the user experience will degrade as the browser will lock up.
P.S. You shouldn't need to parseJSON - if response has the correct mime-type set, jQuery will intelligently guess the type and parse the JSON automatically. And in case the server isn't sending back the correct mime-type, you can also explicitly tell jQuery what the expected return data type is; see the dataType argument to $.get() .
One way you might modify your code, to force synchronous requests:
$.ajax({
type: 'GET',
url: 'data/partners.json',
success: function(file){
partnerData = $.parseJSON(file);
//ideally you would perform a callback here
//and keep your requests asynchronous
},
dataType: 'json',
async: false
});
function is proccessed to the end event when ajax is still being proccessed. insert it into callback function
$(function() {
var partnerData;
$.get('data/partners.json', function(file) {
partnerData = $.parseJSON(file);
console.log(partnerData);
});
});
I would say that your problem is the same of the one that I just solved, if $.get is AJAX! and it is setting a variable, to read that variable outside the callback you need to wait the response! So you have to set async=false!
console.log in synchronous and get is async.
try:
$(function() {
var partnerData;
$.get('data/partners.json', function(file) {
partnerData = $.parseJSON(file);
test();
});
function test(){
console.log(partnerData);
}
});
I'm trying to use a closure (I think that's what it is..), I'd just like to execute a function with a local variable at some point in the future, like this:
function boo() {
var message = 'hello!';
var grok = function() { alert(message); }
foo(grok);
}
function foo(myClosure) {
$.ajax({
timeout: 8000,
success: function(json) {
myClosure();
}
}
}
I could get around this by using global variables and such, but would rather use something like the above because it at least seems a bit cleaner. How (if possible) do you do this?
Thanks
----------- Update --------------------
Sorry I wasn't clear - I was wondering if this is the correct syntax for the closure, I tried it out and it seems ok. Thank you.
Your existing code looks perfectly fine except for that missing paren at the end. ;)
If you're looking to understand the concept of closures more deeply, think of it this way: whenever something in a closured language is defined, it maintains a reference to the local scope in which it was defined.
In the case of your code, the parameter to $.ajax() is a newly-created object ("{ timeout: 8000, etc. }"), which contains a newly-created function (the anonymous "success" function), which contains a reference to a local variable ("myClosure") in the same scope. When the "success" function finally runs, it will use that reference to the local scope to get at "myClosure", even if "foo()" ran a long time ago. The downside to this is that you can end up with a lot of unfreeable data tied up in closures -- the data won't be freed until all references to it have been removed.
In retrospect, I may have confused you more than helped you. Sorry if that's the case. :\
Unless you actually want to make an AJAX call, setTimeout might be more along the lines of what you are looking for:
function foo(myClosure) {
setTimeout(myClosure, 8000); // execute the supplied function after 8 seconds
}
If your question was more along the lines of "Am I creating a closure correctly?", then yes, your function boo is doing the right thing.
Is it what you want?
var boo = (function() {
var message = 'hello!';
return function() {
foo(function() {
alert(message);
});
};
})();
function foo(myClosure) {
$.ajax({
timeout: 8000,
success: function(json) {
myClosure();
}
}
}
or just
function boo() {
$.ajax({
timeout: 8000,
success: function(json) {
alert('hello!');
// do sth with json
// ...
}
}); // <- missed a paren
}
The example is too simple to know what you want btw.