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').
Related
This one will require some setup for you to understand what I am trying to do. It involves both templating and asynchronous calls. I am aware of the intricacies and nuances of async calls.
I have a piece of javascript, in a .js file. The script contains some "tags" that need to be replaced with actual variables, which are different on each use. You will notice the "{{tags}}" embedded in the script. You will also notice that the script contains an ajax call to a C# Generic Handler. :
// this is template code from LoadFlights.js, called from LoadFlights() in main.js...
$.ajax({
type: "POST",
url: "js/handlers/LoadFlights.ashx",
dataType: "text",
cache: false,
data: {
DateStart: "{{DATESTART}}",
DateEnd: "{{DATEEND}}",
Specific: JSON.stringify({DAY: "{{DAY}}", DEP: "{{DEP}}", CARRIER: "{{CARRIER}}", FLT: "{{FLT}}", LEGCD: "{{LEGCD}}"})
},
success: function (result) {
callback_LoadFlights(result);
},
error: function (result) {
alert(result.responseText);
return false;
}
});
function callback_LoadFlights(result) {
alert(result);
}
// end
I get the script with a jquery .get() call, and in the .done() callback, I attempt to assign the retrieved script code to a variable.
function runScript(source, parameters) {
if (URLExists(source)) {
var getScript = $.get({
url: source,
dataType: "script"
})
.done(function (scriptCode) {
var code = scriptCode;
// replace any passed parameters...
for (var p in parameters) {
code = code.replace("{{" + p + "}}", parameters[p]);
}
// remove any unused parameter placeholders...
while (code.indexOf("{{") >= 0) {
code = code.substr(0, code.indexOf("{{")) + code.substr(code.indexOf("}}") + 2);
}
var s = document.createElement('script');
s.type = "text/javascript";
s.text = code;
document.body.appendChild(s);
})
.fail(function () {
alert("Failed to retrieve script: " + source);
})
}
(I omitted the else for brevity sake.)
What happens is that on this line:
var code = scriptCode;
The code immediately executes, and the Generic Handler call fires, and immediately fails with "invalid date format" (the first line that attempts to use DateStart) because DateStart still equals "{{DATESTART}}". None of the code that replaces the tags executes.
Even if I set a breakpoint on that line and attempt to step INTO it to see what might be happening, it still immediately fires the generic handler call.
In the debugger, I typeof'd both code and scriptCode in the Immediate Window, and both return "string".
I'm tempted to believe that a JavaScript error of some sort is occurring, immediately killing the JavaScript code block and stopping it's execution.
But HOW is the Generic Handler being fired then? By all appearances, it seems as though the javascript retrieved by the .get().done() is being executed by simply assigning it to another variable. Is this even possible? Can anyone see what is wrong here?
Take a look at the documentation for jQuery.ajax(): http://api.jquery.com/jquery.ajax/
When the dataType is script:
"script": Evaluates the response as JavaScript and returns it as plain text.
So jQuery is evaluating your javascript before you've had a chance to parse it. Then it gives you the text of the script, but by this point it's too late. Try changing the datatype to 'text' then parse it.
I have a function, that call a controller method using ajax
function CallService(data) {
$.ajax({
url: '#Url.Action("MyMethod", "MyController")',
type: 'GET',
dataType: 'json',
cache: false,
data: { 'serializedMessage': data }
});
MyMethod() returns a complex object and I need to display some properties on the page.
<script>
$(function(){
// create inputData
function (inputData) {
var myItem = CallService(inputData);
$('#name').text(myItem.Name);
};
});
</script>
As ajax returns nothing, I get an error message 'myItem is undefined' on the page. Can anyone explain how to return a variable and use it in JS functions, please?
I'm surprised you couldn't find an example of this anywhere already, but here goes:
There are a few different ways of defining callbacks which can run when the ajax call completes, as shown in the docs at http://api.jquery.com/jquery.ajax/. Here is one, based on the promises API:
function (inputData) {
$.ajax({
url: '#Url.Action("MyMethod", "MyController")',
type: 'GET',
dataType: 'json',
cache: false,
data: { 'serializedMessage': inputData }
}).done(function(result) {
console.log(JSON.stringify(result)); //just for debugging, to see the structure of your returned object
$('#name').text(result.Name);
});
}
One thing you need to grasp is that ajax calls run asynchronously, so the structure you had before will not work - you can't return anything directly from your "CallService" wrapper, which kind of makes it redundant. You have to wait until the ajax call completes, and run any code which depends on the result within (or within a function called from) the "done" callback.
As per the docs I linked to you can also define other callbacks for tasks such as handling errors, if you so desire.
You must use success:function(response){
}
I am confused as to why I cannot get text updates during a javascript/jquery/ajax execution.
I have the following code.
$("#updates").html("Collecting your team names.");
YourTeamFirst(YourTeam, TeamValue);
$("#updates").html("Collecting their team names.");
TheirTeamNext(TheirTeam, TeamValue);
$("#updates").html("Gathering ID's.");
setNames(TeamValue);
$("#updates").html("Setting Details.");
setChampRatios(TeamValue);
$("#updates").html("Setting Ratios.");
setChampKDRS(TeamValue);
$("#updates").html("Finished!");
i.e.
Example function (the only ajax that occurs is in the sub-functions, the actual function calls and text updates are in a plain JS function, no ajax on that...)
function TheirTeamNext(TheirTeam, TeamValue) {
$.ajax({
url: "/PlayerLookUp/TheirRankedData",
type: "POST",
data: "IDList=" + T[i],
dataType: "json",
async: false,
success: function (resp) {
//just boring logic
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
if (XMLHttpRequest.status == 0) {
alert("Issue with reaching Riot API server. Pleast contact an Admin.");
}
}
});
}
And the only thing that ever appears is "Finished" (after the script is done), why won't anything else appear at all? The execution takes about 10 seconds so other updates should be popping up in the innerHtml/Html. I have also tried using document.getElementById("updates").innerHTML = ..., which also shows nothing then when its done will show the "Finished" text.
Each function is either JQuery, Ajax, or javascript with a few back and forth's from my C# controller, but I feel like the text updates should still be updating my innerHtml text unless there is some script thing I am unaware of for innerHtml/Html...
ALSO: If I toss in an alert() somewhere, the most previous text update will appear. So how come only an alert interruption or end of script execution will update/post my text. I would like my users to see updated messages on going with the script.
because ajax is executed ansynchronous.
if you want text like that to appear, you need to use callbacks in your ajax functions.
update: since you are using async: false this behaviour seems really strange, but I don't know how javascript and jquery exactly handle synchronous calls in your case.
one hotfix-suggestion would be to still add callbacks to your functions. (note: this is a very messy workaround and should just help you hotfixing your problem.)
function YourTeamFirst(YourTeam, TeamValue, callback) {
/* ... */
$.ajax({
/* ... */
success: function (resp) {
/* ... */
callback();
}
});
}
then in your function calls add anonymous functions as callback-parameter. in the body of these functions always add the .html() for the next function to be executed.
$("#updates").html("Collecting your team names.");
YourTeamFirst(YourTeam, TeamValue, function () {
$("#updates").html("Collecting their team names.");
});
TheirTeamNext(TheirTeam, TeamValue, function () {
$("#updates").html("Gathering ID's.");
});
/* ... */
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
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 ..
}