why the javascript variable doesn't change among function? - javascript

my problem with the following javascript function:
function ValidateDates() {
var valid = false;
birthD = $("#cp1_txtBirthDate").val();
initialD = $("#cp1_txtInitialDate").val();
var regexp = new RegExp("^([1-9]|(0|1|2)[0-9]|30)(/)([1-9]|1[0-2]|0[1-9])(/)((20|19|18)[0-9]{2})$");
if (birthD != "__/__/____" && initialD != "__/__/____") {
if (regexp.test(initialD) && regexp.test(birthD)) {
$.get("ValidateDates.aspx?BirthD=" + birthD + "&InitialD=" + initialD, function (data) {
if (data == 0) {
valid = true;
$("#Dates_span").html("");
}
else {
$("#Dates_span").html("*" + data);
valid = false;
}
});
}
}
return valid;
}
here when i check the variable valid i found it "false" even if its true, because the initial for it is false from the beginning of function so how to solve it and what is wrong?

When you're doing an asynchronous call, you can't return a value like that. Instead, you should pass in a callback:
function ValidateDates(callback) {
var valid = false;
birthD = $("#cp1_txtBirthDate").val();
initialD = $("#cp1_txtInitialDate").val();
var regexp = new RegExp("^([1-9]|(0|1|2)[0-9]|30)(/)([1-9]|1[0-2]|0[1-9])(/)((20|19|18)[0-9]{2})$");
if (birthD != "__/__/____" && initialD != "__/__/____") {
if (regexp.test(initialD) && regexp.test(birthD)) {
$.get("ValidateDates.aspx?BirthD=" + birthD + "&InitialD=" + initialD, function(data) {
if (data == 0) {
valid = true;
$("#Dates_span").html("");
}
else {
$("#Dates_span").html("*" + data);
valid = false;
}
callback(valid);
});
}
}
}
Then, call it like:
ValidateDates(function(isValid)
{
// Do something with isValid
});

What's wrong is that $.get is an asynchronous call, what that means is that the function doesn't wait until the result is returned from $.get call. It just makes the call and continues execution - so valid = true is set long after false has been returned.

Related

function keeps returning undefined array using Async Await

Can't get my getJSON function to return the array. I've been trying to use await/async but I'm doing something wrong.
.map and .filter should be synchronous but I've tried putting await on them as well.
$(function() {
$("#roll").click(async function() {
var x = await getTreasure()
chrome.extension.getBackgroundPage().console.log(x)
});
});
function getTreasure() {
var sizeValue = $('input[name=size]:checked').val();
var crValue = $('input[name=challenge]:checked').val();
var die = Math.floor((Math.random() * 100) + 1);
var url = "";
if (sizeValue == "individual") {
url = chrome.runtime.getURL("treasure_individual.json");
} else {
url = chrome.runtime.getURL("treasure_horde.json");
};
$.getJSON(url, function(data) {
var match = data.treasure.filter(function (e) {
return e.cr == crValue;
});
for (i in match[0].roll) {
var str = match[0].roll[i].d100;
var arr = str.match(/([0-9]+)/g);
var levels = $.map(arr, function (x) {
return parseInt(x, 10);
});
if (die == levels[0] || die >= levels[0] && die <= levels[1]) {
chrome.extension.getBackgroundPage().console.log(levels);
return levels;
} else {
return die;
};
};
});
};
Edit:
Ok, didn't understand await still needed a Promise. But I'm still not getting it. Tried adding the return Promise around the getJson function but it's still not returning levels.
function getTreasure() {
var sizeValue = $('input[name=size]:checked').val();
var crValue = $('input[name=challenge]:checked').val();
var die = Math.floor((Math.random() * 100) + 1);
var url = "";
if (sizeValue == "individual") {
url = chrome.runtime.getURL("treasure_individual.json");
} else {
url = chrome.runtime.getURL("treasure_horde.json");
};
return new Promise(resolve => {
$.getJSON(url, function(data) {
var match = data.treasure.filter(function (e) {
return e.cr == crValue;
});
for (i in match[0].roll) {
var str = match[0].roll[i].d100;
var arr = str.match(/([0-9]+)/g);
var levels = $.map(arr, function (x) {
return parseInt(x, 10);
});
if (die == levels[0] || die >= levels[0] && die <= levels[1]) {
//chrome.extension.getBackgroundPage().console.log(levels);
return levels;
};
};
});
});
};
The way to return the promise is not by adding new Promise (which is an anti-pattern in this case), but to get the promise that jQuery already has for you:
return $.getJSON(url, function(data) {
// ^^^^^^
// .......
}).promise();
// ^^^^^^^^^^
NB: in your second attempt you never called resolve.
If you need some specific data to be "promised", then chain a then instead of using the callback of $.getJSON. Like this:
return $.getJSON(url).then(function(data) {
// ^^^^^^ ^^^^^^
// .......
return levels;
});

value is not added to multidimensional array

The first time the function fires I get this result:
output1:test
The output2 2 alert is not firing. I know something is probably undefined in alert Does anyone know why the value won't be added in the multidimensional array?
I expect this to display after the false1:
output2:test2
Also if you want to fiddle with the code here it is:
https://jsfiddle.net/ndf0sjgf/1/
var carSelectedArray = [
[null]
];
addRow(carSelectedArray);
addRow(carSelectedArray);
function addRow(carSelectedArray) {
var arrayempty = false;
if (carSelectedArray[0][0] == null || carSelectedArray.length == 0) {
arrayempty = true;
} else {
arrayempty = false;
}
if (arrayempty == true) {
carSelectedArray[0][0] = "test";
alert("output1:" + carSelectedArray[0][0]);
} else {
carSelectedArray[1][0] = "test2";
alert("output2:" + carSelectedArray[1][0]);
}
}
Your loop works well, however your didn't define your array well.
there is only 1 dimension here :
var carSelectedArray = [[null]];
So replace with this :
var carSelectedArray = [[],[]];
PS : null is not required
and at the beginning in your function, you define arrayempty to false, so you can remove this :
else {
arrayempty = false;
}
Solution here : https://plnkr.co/edit/Qikalr0jc54R3MRSea4G?p=preview
var carSelectedArray = [[],[]];
addRow(carSelectedArray);
addRow(carSelectedArray);
function addRow(carSelectedArray) {
var arrayempty = false;
if (carSelectedArray[0][0] == null || carSelectedArray.length == 0) {
arrayempty = true;
}
if (arrayempty == true) {
carSelectedArray[0][0] = "test";
alert("output1:" + carSelectedArray[0][0]);
} else {
carSelectedArray[1][0] = "test2";
alert("output2:" + carSelectedArray[1][0]);
}
}

how to return value inside of forEach loop in JavaScript

I got stuck with my code.
I wrote this sample code only for the purpose to reproduce my problem, so this code is not practical at all but I hope you get my point.
In the code below, for the last value to be output, I expect it to be 3, but it's undefined.
How am I supposed to write if I want the last value to be 3 in this case??
This is just a sample code, but in the actual code, I fetch content from amazon api and when it returns api error, I want to run the same function again after 1000 milli seconds.
var list = [1,2,3];
var someClass = new SomeClass();
list.forEach(function(value) {
var result = someClass.getSomething(value);
console.log("outside: " + result);
});
function SomeClass() {
var flag = false;
this.getSomething = function(something) {
if (something === 3 && flag === false) {
flag = true;
this.getSomething(something);
//I need to return here, so the succeeding code is not read.
return;
}
console.log("inside: " + String(something));
return something;
}
}
Log
inside: 1
outside: 1
inside: 2
outside: 2
inside: 3
outside: undefined // I expect this value to be 3!!!
You have a test:
if (something === 3 && flag === false) {
//...
return;
If you want to return 3 then don't have a return statement with nothing after it. return means return undefined. Put return 3 or return something.
You probably want to return from your recursive call though:
return this.getSomething(something);
Here's the problem:
function SomeClass() {
var flag = false;
this.getSomething = function(something) {
if (something === 3 && flag === false) {
flag = true;
this.getSomething(something); // not returning this
return; // returning undefined
}
console.log("inside: " + String(something));
return something;
}
}
Here's the fix:
function SomeClass() {
var flag = false;
this.getSomething = function(something) {
if (something === 3 && flag === false) {
flag = true;
return this.getSomething(something);
}
console.log("inside: " + String(something));
return something;
}
}
change the code to
if (something === 3 && flag === false)
{
flag = true;
return this.getSomething(something);
}
"return;" returns undefined
It returns undefined in your code because you return; in the if clause.
return this.getSomething(something) within the if clause
var list = [1, 2, 3];
var someClass = new SomeClass();
list.forEach(function(value) {
var result = someClass.getSomething(value);
console.log("outside: " + result);
});
function SomeClass() {
var flag = false;
this.getSomething = function(something) {
if (something === 3 && flag === false) {
flag = true;
return this.getSomething(something);
}
console.log("inside: " + String(something));
return something;
}
}
forEach loop doesn't return a value.
You can create a global variable and assign values to it.

Passing variable between javascript functions not working?

I tried using this method to pass a variable to the next function:
function a(form, ctr) {
var a = form;
var b = ctr;
b(ctr);
}
function b(ctr) {
var b = ctr;
}
The exact code is a lot more complicated as i'm using the POST method with ajax: function a begins upon a click and uses both the form and ctr parameters - it then goes to function b which only needs ctr - however this method of passing the variable hasn't worked. Any better solution?
function updateQuestion(form, ctr) {
console.log("Called updateQuestion");
var str1 = "toggleDiv";
var str2 = ctr;
var id = str1.concat(str2);
var divVar = document.getElementById(id);
console.log(divVar);
var getdate = new Date(); //Used to prevent caching during ajax call
if(XMLHttpRequestObject) {
console.log("XMLHttpRequestObject = TRUE");
var myVar = form.create_mcq_question.value;
console.log("MyVar = " + myVar);
var formQuestion = document.getElementById("formQuestion");
console.log("1");
XMLHttpRequestObject.open("POST","hiddent",true);
console.log("2");
XMLHttpRequestObject.onreadystatechange = handleServerResponse;
console.log("3");
XMLHttpRequestObject.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
console.log("4" + document.getElementById("create_mcq_question").value);
var mcqid;
var mcqQuestion;
var mcqAnswerCorrect;
var mcqAnswerWrong1;
var mcqAnswerWrong2;
var mcqAnswerWrong3;
var mcqExplanation;
var error = 0;
if (form.create_mcq_question.value == "" || form.create_mcq_question.value == null ) {
error = 1;
}
else {
mcqQuestion = form.create_mcq_question.value
}
if (form.create_mcq_answer_correct.value == "" || form.create_mcq_answer_correct.value == null) {
mcqAnswerCorrect = "";
error = 1;
}
else {
mcqAnswerCorrect = form.create_mcq_answer_correct.value
}
if ((form.create_mcq_answer_wrong1.value == "" || form.create_mcq_answer_wrong1.value == null) && (form.create_mcq_answer_wrong2.value == "" || form.create_mcq_answer_wrong2.value == null) && (form.create_mcq_answer_wrong3.value == "" || form.create_mcq_answer_wrong3.value == null)) {
error = 1;
}
if (form.create_mcq_answer_wrong1.value == "" || form.create_mcq_answer_wrong1.value == null) {
mcqAnswerWrong1 = "";
}
else {
mcqAnswerWrong1 = form.create_mcq_answer_wrong1.value
}
if (form.create_mcq_answer_wrong2.value == "" || form.create_mcq_answer_wrong2.value == null) {
mcqAnswerWrong2 = "";
}
else {
mcqAnswerWrong2 = form.create_mcq_answer_wrong2.value
}
if (form.create_mcq_answer_wrong3.value == "" || form.create_mcq_answer_wrong3.value == null) {
mcqAnswerWrong3 = "";
}
else {
mcqAnswerWrong3 = form.create_mcq_answer_wrong3.value
}
if (form.create_mcq_explanation.value == "" || form.create_mcq_explanation.value == null) {
mcqExplanation = "";
}
else {
mcqExplanation = form.create_mcq_explanation.value
}
if (error == 0) {
XMLHttpRequestObject.send("create_mcq_question=" + mcqQuestion +
"&create_mcq_correct_answer=" + mcqAnswerCorrect +
"&create_mcq_wrong_answer1=" + mcqAnswerWrong1 +
"&create_mcq_answer_wrong2=" + mcqAnswerWrong2 +
"&create_mcq_answer_wrong3=" + mcqAnswerWrong3 +
"&create_mcq_explanation=" + mcqExplanation +
"&mcqid=" + mcqid );
console.log("5");
handleServerResponse(ctr);
}
else {
document.getElementById("divVar").innerHTML="Cannot update question - please ensure all required fields are filled!";
}
}
}
function handleServerResponse(ctr) {
var str1 = "toggleDiv";
var str2 = ctr;
var id = str1.concat(str2);
var divVar = document.getElementById(id);
console.log("Handle server response called");
if (XMLHttpRequestObject.readyState == 1) {
console.log("Loading");
document.getElementById(divVar).innerHTML="<img src=\"hidden">";
}
if (XMLHttpRequestObject.readyState == 4) {
console.log("4");
if(XMLHttpRequestObject.status == 200) {
document.getElementById(divVar).innerHTML=XMLHttpRequestObject.responseText; //Update the HTML Form element
console.log("divVar found");
console.log(divVar);
}
else {
document.getElementById(divVar).innerHTML="There was a problem updating your question - please try again!"; //Update the HTML Form element
console.log("divVar not found");
console.log(divVar);
}
}
}
And the button which starts the whole thing off:
<input type="button" value="Update My Question!" onclick="updateQuestion(this.form,<?php echo" $ctr"; ?>)">
Firebug showing the first function working, and calling the second one, which doesn't get the variable:
[02:21:42.106] Called updateQuestion
[02:21:42.106] [object HTMLDivElement]
[02:21:42.106] XMLHttpRequestObject = TRUE
[02:21:42.106] MyVar = Gram- bacteria are stained purple with gram staining, while gram+ bacteria are stained pink.
[02:21:42.106] 1
[02:21:42.107] 2
[02:21:42.107] 3
[02:21:42.107] 4Gram- bacteria are stained purple with gram staining, while gram+ bacteria are stained pink.
[02:21:42.108] Handle server response called
[02:21:42.108] Loading
[02:21:42.108] 5
[02:21:42.108] Handle server response called
[02:21:42.109] Loading
[02:21:42.649] Empty string passed to getElementById(). # hidden
[02:21:42.649] TypeError: document.getElementById(...) is null # hidden
[02:21:42.647] Handle server response called
[02:21:42.648] 4
There is already a variable called 'b' inside your function scope. That's why you get the error. If they are global functions, you can use:
function a(form, ctr) {
var a = form;
var b = ctr;
window.b(ctr);
}
function b(ctr) {
var b = ctr;
}
The following makes no sense really:
var b = ctr;
b(ctr);
Here the variable b is treated and invoked as function, and you pass a reference to itself as the parameter. Is that really our intention?
Edit: Now with the additional info, the problem is easy to explain. If you look at your log, you'll notice that the handleServerResponse is invoked several times. The first time "ctr" is passed as expected.
The problem is here:
XMLHttpRequestObject.onreadystatechange = handleServerResponse;
This sets a callback, and the callback will invoke your function without the "ctr" of course, which is why your code runs as it does. You could use an anonymous function so that a closure is used:
XMLHttpRequestObject.onreadystatechange = function() { handleServerResponse(ctr); };
You may want to read JavaScript: The Good Parts by Crockford, I think it would help to improve your JS coding significantly.

Checking multiple variables' values to make sure they all match

How do I efficiently check to see if multiple variables' values all match? The following function should return true if they match and false if they don't:
function projectIsLocked (data) {
if (data.ArchiveSnapshotID === data.CurrentSnapshotID === data.LiveSnapshotID) {
return true;
}
return false;
}
I thought I could just use if (data.ArchiveSnapshotID === data.CurrentSnapshotID === data.LiveSnapshotID) but it doesn't seem to work.
Ideas for something simple?
If there are just 3 comparisons , then this should be enough.
function projectIsLocked (data) {
var archive = data.ArchiveSnapshotID;
var current = data.CurrentSnapshotID;
var live = data.LiveSnapshotID;
return (archive === current && current === live)
}
Why not push them all to an array. This way you can use as many.
function check_for_equal_array_elements(my_array){
if (my_array.length == 1 || my_array.length == 0) {
return true;
}
for (i=0;i<my_array.length;i++){
if (i > 0 && my_array[i] !== my_array[i-1]) {
return false;
}
}
return true;
}
//Example:
var my_array = [];
my_array.push(5);
my_array.push(5);
// will alert "true"
alert("all elements equal? "+check_for_equal_array_elements(my_array));
my_array.push(6);
// will alert "false"
alert("all elements equal? "+check_for_equal_array_elements(my_array));
The problem here is, that a part of the logical expression is evaluated and then compared, so data.ArchiveSnapshotID === data.CurrentSnapshotID evaluated to "true" and data.LiveSnapshotID is checked against true, which you can see here (LiveSnapshotID was changed to boolean true):
function projectIsLocked (data) {
if (data.ArchiveSnapshotID === data.CurrentSnapshotID === data.LiveSnapshotID) {
return true;
}
return false;
}
var data = { ArchiveSnapshotID: "foo", CurrentSnapshotID: "foo", LiveSnapshotID: true };
alert(projectIsLocked (data));
You might want to use something like this, which is quite extensible for even more properties.
function projectIsLocked (data) {
var props = ["ArchiveSnapshotID", "CurrentSnapshotID", "LiveSnapshotID"];
for (var i = 1; i < props.length; i++)
{
if (data[props[i]] !== data[props[i - 1]])
return false;
}
return true;
}

Categories

Resources