Unable to get the length - javascript

I am novice to javascript concepts.
Why i am getting the different output for the same variable length?
While it is showing the expected result inside the body ?
var length;
element.all(by.className("className")).getText().then(function(items){
length = items.length;
console.log("1st output = "+length);//1
console.log("2nd output = "+items.length);//1
});
console.log("3rd output = "+length);//undefined
Output:-
1st output = 1
2nd output = 1
3rd output = undefined

Because your all() is async call so console.log will run before you finish then chain and assign value to length

The element.all(by.className("className")).getText()) call in your function returns something called a promise- it executes some code, and after this code is executed, it calls the function inside .then(). However, this happens independently of the rest of your program- so it continues to execute the console.log after the .then() statement.
This leads to what is called a race condition- where the order of operations can be undefined.

All before answers already explain what happens and why. So it's clear, that your 3rd console.log is executed before your then() condition finishes.
What you can try is this:
var length;
element.all(by.className("className")).getText().then(function(items){
length = items.length;
console.log("1st output = "+length);//1
console.log("2nd output = "+items.length);//1
});
browser.waitForAngular(); //add this line to let Protractor wait for Async tasks to be resolved first
console.log("3rd output = "+length);
However, keeping the 3rd console.log() inside the then() statement would be the more proper solution.

Related

Issues with populating arrays from csv(dsv) parsing

I am quite new to javascript, basically using it for the first time to write a histogram plotter application. My issue is, I am importing a data file and ideally sending (some of) the entries into an array. Problem is that once I do that, I have troubles accessing the entries in my array.
How could I fix that? Posting the code below in case it helps.
Thank you!
let filename = 'uploads/testdata.dat';
const data_e = new Array();
d3.dsv(" ",filename, (event)=>{
data_e.push(event.mass);
return data_e
})
console.log(data_e);
Which outputs
Array []
​
0: "734.770828169"
​
1: "85.0912893849"
​
2: "87.383924186"
​
...
However if I wanna get a value:
console.log(data_e[0]) //output: undefined
Edit1: the values I'm pushing are in console.log(event.mass).
output:
734.770828169 analyzer.php:19:12
85.0912893849 analyzer.php:19:12
87.383924186 analyzer.php:19:12
(...)
Edit2: If I call console.log(data_e) inside the dsv function I get a line for each iteration while my array gets filled, ending with
Array(7178) [ "734.770828169", "85.0912893849", "87.383924186", "1274.99805502", "91.5349415148", "80.2766459668", "1396.69489276", "91.5584443363", "94.52017453", "1582.29197222", … ]
Which is, indeed the object I want to get. But what if I want to carry that outside the function dsv(), so that I get the same output as above?
Edit3: Calling console.log(JSON.stringify(event.mass)) gives:
again, one line for each 'iteration' (I think), and it makes sense. I just want to use the full array outside that function (or maybe it's just a silly thing to do .-.)
"734.770828169" analyzer.php:19:12
"85.0912893849" analyzer.php:19:12
"87.383924186" analyzer.php:19:12
"1274.99805502" analyzer.php:19:12
(...)
Do not use return inside the loop, because you then leave it immediately. Whatsmore, I think d3.dsv() is an asynchronous function. Means your console log outside this method must return undefined as Javascript does not wait for d3.dsv() to finish. And your Array data_e is currently undefined.
let data_e = new Array();
Instantiate it this way and you'll see, that console.log() will output [] instead of undefined.
let data_e = [];
d3.dsv(" ",filename, (event)=>{
// your code
})
console.log(data_e);
Actually, I could not find a manual about how to get a trigger when d3.dsv() is finished. But fo the start try it this way. It's not perfect but it's only supposed to show you that it actually works;
let filename = 'uploads/testdata.dat';
const data_e = new Array();
// run the filter
d3.dsv(" ",filename, (event)=>{
data_e.push(event.mass);
})
// wait 2 seconds, then show the array in the console
setTimeout( () => {
console.log(data_e);
}, 2000);

Issue validating in all rows of a table

I have a table which consist of around 50 rows and columns on a page. I want to fetch all rows from table and write a function to check if 2nd column of all words contains word 'Silver'. I tried below code but it is not working. Can someone please help where i am missing an i am not that great with Javascript promises. If match to string is found, i just want to increment a count and then return count at end.
fetchValues(SearchString){
var matchcount=0;
var count = this.ContentTable.Rows.count();
for (var i=0;i<count-1;i++) {
return this.ContentTable.element(by.css('[id*="DXDataRow'+i+'"]'))
.then((Row) =>{
return this.ContentTable.Row.element(by.css('[id*="uxSetList_tccell'+i+'_1"]'))
.then((Column)=>{
var CoinInfo = this.ContentTable.Row.Column.element(by.css('a')).getText();
if (CoinInfo.indexOf(SearchString)>=0)
{
matchcount =matchcount+1
}
return matchcount;
});
});
}
}
first of all, you're returning a value from inside your for() loop. That guarantees your loop is only ever going to be run once, and you're only ever going to examine one row. Is that what you want? (no, really, I have no idea.) Are you trying to create a lot of promises and combine their results into a single number? You might want to use Promise.all() to combine the values of all promises you create, and return a value from that meta-promise:
var myPromises = [];
for (var i = 0; i < count; i++) {
myPromises.push(this.ContentTable.element(by.css('[id*="DXDataRow'+i+'"]'))
.then(/* ...blah blah blah ... */)
);
}
// return a single value from this function containing data from all promises
return Promise.all(myPromises).then((promiseResultsArray) => {
/* calculate match count */
});
second, I think your promises themselves are written incorrectly. You're assuming that the value of i when your promise's callback is run is the same as the value of i when your promise's callback was defined. Because of how promises work in JS, that's not actually the case.
What's happening is that your for() loop creates a bunch of promises and then, at some undefined point in the future, one of these promises gets resolved and the function you passed to its .then() method gets run. This function knows about i - it's right there in the function body, after all! - but the value of i right now is equal to the value of count - 1. We're in the future now, remember, and the for() loop has terminated, and the termination condition for your loop is when i === count - 1. This will be the case for every single promise you create in this loop, because they all get executed after the loop terminates.
You can fix this in a bunch of ways. Probably the cleanest is to declare a new variable, initialized to the current value of i and never ever changed, and refer to that inside your .then() callback:
var i = 0;
var myPromises = [];
for (i = 0; i < count; i++) {
var currentCount = i;
myPromises.push(this.ContentTable.element(by.css('[id*="DXDataRow'+currentCount+'"]'))
.then(/* ...blah blah blah ... */)
);
}
// return a single value from this function containing data from all promises
return Promise.all(myPromises).then((promiseResultsArray) => {
/* calculate match count */
});
if you want more information, there are plenty of SO questions about how to use promises.

extra output after loop

I am learning JavaScript on Codecademy. I am finding so many outputs like below when I use while loop.
for (var i=0; i<5; i++){
console.log("Dhanu identify problems and solve them");
}
var loop = 0;
while(loop<5){
console.log("Do some more");
loop++;
}
I am getting an unwanted output in the last line as 4.
The output you get is simply console.log which logs the last known value of the 'loop' variable: (here in firefox):
It's absolutely not related to your code and you don't have to worry about that.
As stated in another answer, debug console use to log the result of the last line (probably because they are meant to debug).
For example the statement "i = 1" evaluates to "1":
while the statement "var i = 1;" evaluates to "undefined", hence logging "undefined"
you can observe the same behavior by invoking eval on those statements:
You're seeing that because the last statement in your while loop is loop++, which "returns" the current value of loop. This is just a side effect of running code in a console like this. Consoles are basically read-execute-print-loops (REPL), and so they need something to print. If you ran this as a script in a webpage you would not see 4
when you write any statement in developer console then last returned value will be printed...
for example
var a;
it prints undefined on console.
a = 10;
it prints 10 on console.
a = 10; a = a + 5;
it prints 15 on console.
simply when we assign any values or increment or decrement numbers then it returns value after performing that operation...
so, in the above or below code
var loop = 0;
while(loop<5){
console.log("Do some more");
loop++;
}
finally loop++ is 4.

Why the eval() is not working with array

What's wrong with this code? Can anyone help out?
var read=new Array("i=10","j=20","k=i*j");
for(var i=0;i<read.length;i++)
{
alert(eval(read[i]));
}
Expecting output:
alert three times with values 10,20,200.
But actual output:
But alert Once with value 10.
When the loop executes the first time, you are setting i = 10, with eval. So the loop breaks out immediately.
So, you might want to change the loop variable to something else, like this
var read = new Array("i=10","j=20","k=i*j");
for(var idx=0; idx < read.length; idx++)
{
console.log(eval(read[idx]));
}
Output
10
20
200
Note: Please make sure that you read this question and the answers to that question, before using eval in your code.
Try this code
var read=new Array("i=10","j=20","k=i*j");
for(var index=0;index<read.length;index++)
{
alert(eval(read[index]));
}
while the loop is executing, at the first execution of i=10 the i variable is set to 10; so loop will be terminated because of the condition i<read.length (here... 10<3) remains false.
see the eval() tutorial.

Return value coming through as undefined

If I console.log the output from count+1, I get a correct number value. If I output the value of note.note_id, I get undefined. Why is this?
I have tried setting value to a predefined one inside the function.
note.note_id = db.notes.count(function(err, count) {
return count + 1;
});
Hard to answer without knowing what db.notes is but it seems to be something accessing a database. This means it's most likely asynchronous which meansa that the count() method will never return a value but you need to do whatever you want to do with the result inside the callback.
db.notes.count(function(err, count) {
note.note_id = count + 1;
// do more stuff here
});
// do NOT do stuff here. it will run BEFORE the callback has been executed

Categories

Resources