I am getting an error while setting a class property in javascript class. I am using nodejs prompt module to get user input and setting it to the class property. But i am getting following error.
TypeError: Cannot read property 'resultAge' of undefined
I figured it out that it has something to do with synchronization, but i am not able to figure it out that how to implement it for this situation.
Also i want to prompt user again until he has entered a valid number (I can not use a do while loop, what might be the solution?)
var prompt = require("prompt");
var ageTotal = function(){
this.resultAge = 0;
this.getUserAge = function(){
prompt.start();
//i want to run this until valid input is entered
prompt.get(["age"], function(err, result){
//I know i have to convert userInput to int but thats for later
this.resultAge += result.age
});
}
}
ageTotal.prototype.displayTotalAge = function(){
return this.resultAge;
}
var a = new ageTotal();
a.getUserAge();
var age = a.displayTotalAge();
console.log(age); //This is running before the above function finishes
EDIT:
The problem setting resultAge is solved but now the problem is var age = a.displayTotalAge(); is evaluated after console.log(age) which results in 0;
You need to pass the scope of ageTotal into the prompt.get callback:
var ageTotal = function(){
this.resultAge = 0;
this.getUserAge = function(){
var that = this;
prompt.start();
prompt.get(["age"], function(err, result){
that.resultAge += result.age
});
}
}
Related
I've separated the variables for scoping purposes, I'm able to fill out all the variables with the respective DOM elements from url1 but when I try to pass them to url2 fields, they get set to undefined as if the variable was never set. Yet the console.log works... I've passed also a function to .setValue('#address-serviceability-form', '', '', function(e){ // set the value here}) but still I get undefined... Is this variable scoping issue?
describe('Ecosia.org Demo', function() {
var address ='';
var streetNumber = '';
var city = '';
var stateAndZip = '';
var state = ''
var zip = '';
before(browser => browser.url('url1.com'));
test('Extract random address', function (browser) {
browser
.getText('.rand_large li:first-child', function(result) {
address = result.value.split("\n");
streetNumber = address[0];
console.log('streetNumber', streetNumber) //this works and logs correctly
city = address[1].split(",")[0];
stateAndZip = address[1].split(",")[1];
state = stateAndZip.split(" ")[1];
zip = stateAndZip.split(" ")[2];
})
.url('url2.com')
.waitForElementVisible('form')
.setValue('#address-serviceability-form', streetNumber) // this is set to undefined
.pause(5000)
});
after(browser => browser.end());
});
This looks to me to be a problem with your understanding of NodeJS callbacks.
You should be able to fix this using async/await. Your code is not waiting for the callback to be resolved and the value is not assigned before being used in set value function. you could try something like below.
test('Extract random address', async function(browser) {
await browser
.getText('.rand_large li:first-child', function(result) {
address = result.value.split("\n");
streetNumber = address[0];
console.log('streetNumber', streetNumber) //this works and logs correctly
city = address[1].split(",")[0];
stateAndZip = address[1].split(",")[1];
state = stateAndZip.split(" ")[1];
zip = stateAndZip.split(" ")[2];
})
browser.url('url2.com')
.waitForElementVisible('form')
.setValue('#address-serviceability-form', streetNumber) // this is set to undefined
.pause(5000)
});
setInterval(function(){
for(i=1;i<=len;i++)
{
plug[i].getSysInfo().then(data => {
var json = JSON.stringify(data,undefined,2);
var obj = JSON.parse(json);
var _macadd = obj.mac;
plug[i].getConsumption().then(data => {
var json = JSON.stringify(data,undefined,2);
var obj = JSON.parse(json);
var _current = obj.current;
var _voltage = obj.voltage;
var _power = (obj.power).toPrecision(5);
var _total = obj.total;
var _err_code = obj.err_code;
console.log(_power);
//console.log(_macadd);
//console.log(voltage);
if(_power > 1800)
{
_power = 0.00;
}
// var fs = require('fs');
// fs.writeFile("emeter.json", json);
var sql1 = "INSERT INTO emeter SET ? ";
var post1 = { macaddress: _macadd,current: _current,voltage: _voltage,power: _power, total: _total,err_code: _err_code};
var tmp = JSON.stringify(post1,undefined,2);
console.log(tmp);
con.query(sql1, post1, function (err, result) {
if (err) throw err;
console.log("inserted");
});
});
});
}
},30000);
While I run this, I am getting below error
Unhandled promise rejection Type error:
Cannot read property of 'getconsumption' of undefined.
The above code worked well when I replace the index with one value.To retrieve just one value it is working. When it is in For loop then the error message is returned. Please help me in solving this.
You're trying to use a for loop index value inside an asynchronous callback. The problem is that the .then() handlers are called AFTER the for loop has already finished and thus the for loop index is at its terminal value (beyond the end of the array) when you try to use it.
There are many ways to fix this. One simple way would be to change this:
for(i=1;i<=len;i++)
to this:
for(let i=1;i<=len;i++)
Using ES6 let creates a new unique variable for each execution of the for loop so that each one maintains its own copy of the index, even for the duration of the asynchronous calls within that for loop block.
In ES5 (where you don't have let), you could change your loop to use .forEach():
plug.forEach(function(val, index) {
// use val and index here rather than plug[i]
});
This also creates a new val and index variable for each invocation of the loop.
Trying to check if some variables contain things, because they throw errors and break the ajax function when they don't. Problem is that just checking if data[2][0] contains something causes the following error:
Uncaught TypeError: Cannot read property '0' of undefined
I'd very much prefer not to check this in a previous stage. How do I check if data[2][0] is defined, without causing the actual checking to break my js?
Code:
//ajax ^
success: function(data){
var xp = data[0][0]; //Contains a string
var yp = data[1][0]; //Contains a string
var zp = data[2][0]; //Is not set, fails here
if(xp === ''){ //Tried using null & undefined here aswell
//Do nothing
} else {
var one = data[0][0];
var oneH = data[0][1];
var oneS = data[0][2];
}
if(yp === ''){
//Do nothing
} else {
var two = data[1][0];
var twoH = data[1][1];
var twoS = data[1][2];
}
if(zp === ''){
//Do nothing
} else {
var three = data[2][0];
var threeH = data[2][1];
var threeS = data[2][2];
}
//ajax continues v
Any help will be much appreciated.
You should check if a variable is undefined using typeof, not with an equality check against '':
if (typeof myVar === 'undefined')
You can also check if a variable is an array using Array.isArray(myVar)
I would check to see if data[2] exists first, and then redefine zp if it does.
var zp = data[2];
if (zp) zp = zp[0];
I'm writing a simple application where I send values to a mqtt broker given by a pot-meter (variable resistor). The thing I am trying to accomplish is that I only send changed values to save bandwidth. I am trying Object.observe, but that does not do anything. Can anybody help me?
My code:
var analogValue = 0;
every((0.5).second(), function() {
analogValue = my.sensor.analogRead();
var values = {values:[{key:'resistance', value: analogValue}]}
//another experiment here
var arr = ['resitance', analogValue];
Array.observe(arr, function(changes) {
console.log(changes);
});
arr[1] = analogValue
console.log('sent ',values,'to ',thingTopic)
client.publish(thingTopic, JSON.stringify(values));
});
var o = [analogValue];
Object.observe(o, function (changes) {
console.log(changes);
//eventually publish only changes to broker here
})
o.name = [analogValue]
You don't need to use Object.observe. You can just save the last measurement and check the new one against it. Like this:
// I'm assuming that any actual measurement will be different than 0
var lastMeasurement = 0;
every((0.5).second(), function() {
var analogValue = my.sensor.analogRead();
if (lastMeasurement !== analogValue) {
// the new value is different
var values = {values:[{key:'resistance', value: analogValue}]};
client.publish(thingTopic, JSON.stringify(values));
// update the last measurement value
lastMeasurement = analogValue;
}
});
I've been going at a small snippet of code for like an hour or two now, but can't seem to figure out why my Javascript breaks down at the end of this code.
// Getting username from address bar and user ID from username
var siteHref = window.location.href;
var specifiedUser = siteHref.split('#');
var userName = specifiedUser[1];
var userURL = 'http://soundcloud.com/' + userName;
var idGetter = SC.get('/resolve', { url: userURL }, function(user) {
SC.get('/users/', function() {
var userInfo = new Array(3);
userInfo[0] = user.username;
userInfo[1] = user.id;
userInfo[2] = user.public_favorites_count;
console.log(userInfo);
console.log(userInfo[2]);
});
});
I've added the variables at the top for a bit of context. To explain this function passes the two parts of the array that I've specified into the console, which is perfect. Only when I call the variable is shows up as undefined?
I also tried wrapping this in an additional function and has no luck calling it.
Anyone have idea where I've gone wrong?
You are calling two asynchronous functions. The results you get in the second one are ONLY valid inside that callback function or in a function you call from there. You can't use them globally afterwards because the async functions have not yet finished yet and thus they are still undefined.
Plus, if you're asking about the userInfo variable, that goes out of scope as soon as the callback returns so it is not available anywhere else.
See the comments I added to your code:
// Getting username from address bar and user ID from username
var siteHref = window.location.href;
var specifiedUser = siteHref.split('#');
var userName = specifiedUser[1];
var userURL = 'http://soundcloud.com/' + userName;
var idGetter = SC.get('/resolve', { url: userURL }, function(user) {
SC.get('/users/', function() {
var userInfo = new Array(3);
userInfo[0] = user.username;
userInfo[1] = user.id;
userInfo[2] = user.public_favorites_count;
console.log(userInfo);
console.log(userInfo[2]);
// ** you must use userInfo here or call some other function
// ** and pass userInfo to it
});
});
// ** you cannot use userInfo here as it is both out of scope and
// ** has not yet been set
The idGetter value will contain whatever the first call to SC.get() returns which will NOT be the eventual asynchronous result. If you tell us what SC.get() is, then we might be able to help you understand what it returns.
If SC.get() is the SoundCloud function, then it appears that it returns nothing and thus that is why idGetter is undefined.
FYI, I confirmed here in the SoundCloud source that SC.get() does not return anything.
If all you're trying to do is to create a new function that contains all this code and will call a callback when the results are available, you can just define that function and then call it:
function getUserInfo(callback) {
// Getting username from address bar and user ID from username
var siteHref = window.location.href;
var specifiedUser = siteHref.split('#');
var userName = specifiedUser[1];
var userURL = 'http://soundcloud.com/' + userName;
SC.get('/resolve', { url: userURL }, function(user) {
SC.get('/users/', function() {
var userInfo = new Array(3);
userInfo[0] = user.username;
userInfo[1] = user.id;
userInfo[2] = user.public_favorites_count;
console.log(userInfo);
console.log(userInfo[2]);
// ** you must use userInfo here or call some other function
// ** and pass userInfo to it
callback(userInfo);
});
});
// ** you cannot use userInfo here as it is both out of scope and
// ** has not yet been set
}
// then, you can call it like this:
getUserInfo(function(userData) {
// you can use userData here
});
idGetter isn't a function, you can't call it. If you want it to be a function, write:
var idGetter = function () {
SC.get('/resolve', { url: userURL }, function(user) {
SC.get('/users/', function() {
var userInfo = new Array(3);
userInfo[0] = user.username;
userInfo[1] = user.id;
userInfo[2] = user.public_favorites_count;
console.log(userInfo);
console.log(userInfo[2]);
});
});
};
Then you can do idGetter() to run the function.
I can only assume that userInfo[2] is showing as undefined since it would not make since for userInfo to be undefined. If that is the case, then it is probable that user.public_favorites_count is undefined. Trying printing that out to the console, and when it shows up as undefined, you'll need to determine why that is happening. Without more information about what that object is, or the code returning that object, there's not much more help the community will be able to provide.
This seems to either be working, or is a step forward.
var idGetter = function () { SC.get('/resolve', { url: userURL }, function(user) {
SC.get('/users/', function() {
var userInfo = new Array(3);
userInfo[0] = user.username;
userInfo[1] = user.id;
userInfo[2] = user.public_favorites_count;
console.log(userInfo);
console.log(userInfo[2]);
});
});
};
var idGetter = idGetter();
Setting the variable before the function, and re-setting it after. Not sure if this is standard practise, but seems to work to some extent.