Object property always undefined - javascript

This is the first time I've used JS objects and I'm confused as to why this property is always undefined:
function Rotator() {
this.interval = 300;
this.image = 0;
this.images = undefined;
}
Rotator.prototype.Fetch = function(links) {
console.log("Fetch called");
this.images = links;
}
Rotator.prototype.Current = function() {
if (this.images == undefined) {
console.log("Error, images is undefined");
}
return this.images[this.image];
}
r = new Rotator;
$.getJSON("./data.php", function (data) {
r.Fetch(data.images);
});
console.log(r.Current());
The error I get is:
Uncaught TypeError: Cannot read property '0' of undefined
The JSON returned is working fine, and fetch is marked as called in the console (when logged the data is fine as well). Why is Rotator.images always undefined?
Edit: Some console.log results:
Logging data.images in $.getJSON results in correct data.
Logging links in Fetch results in correct data.
Logging this.images in Fetch results in correct data.
Logging this.images in Current results in null.

Because getting JSON is asynchronous, that's why the data is only available in the callback function.
$.getJSON("./data.php", function (data) { // callback function
r.Fetch(data.images); // this will run when the data is available
});
console.log(r.Current()); // this will run immediately -> data.images is null
Everything that depends on the data should be placed in the callback function!

Will this get me purists on my neck or is it acceptable?
Rotator.prototype.Current = function() {
if (this.images) return this.images[this.image];
console.log("Error, images is undefined, null, empty or 0");
}

You can't use undefined that way. Use null instead:
this.images = null;
and
if (this.images == null) {
Edit:
You also have to avoid using the images property if it's null:
Rotator.prototype.Current = function() {
if (this.images == null) {
console.log("Error, images is undefined");
return null;
}
return this.images[this.image];
}

Related

how to get data outside javascript function

im wondering if i can get some help here, im not a skilled coder by far, but im trying to retrieve results outside the function and the result in log im getting is Undefined
var pricecrex;
getDataFromAPI("https://api.crex24.com/CryptoExchangeService/BotPublic/ReturnTicker?request=[NamePairs=BTC_WAGE]",
true,
function(data){
var resultcrex = JSON.parse(data);
if (resultcrex !== "undefined") {
if (resultcrex) {
var pricecrex = resultcrex.Tickers[0].Last
}
else {
msg.reply("0")
}
}
}
);
console.log(pricecrex);
It is because Ajax requests are async. console.log() gets executed before response is received from request, and thus before setting value in pricecrex. So you were getting undefined.
var pricecrex;
getDataFromAPI("https://api.crex24.com/CryptoExchangeService/BotPublic/ReturnTicker?request=[NamePairs=BTC_WAGE]",
true, function(data) {
var resultcrex = JSON.parse(data);
if (resultcrex !== "undefined") {
if (resultcrex) {
pricecrex = resultcrex.Tickers[0].Last;
print(pricecrex);
}
else {
msg.reply("0")
}
}
}
);
function print(data) {
console.log(data);
}
The nature of Javascript is continue running code once an asynchronous function has been started. So you run getDataFromAPI(), and then while that's running, the interpreter goes to the next piece of code, which is your console.log(pricecrex).
So you can either run the console.log(pricecrex) directly in the callback, function(data){}, or to keep things cleaner, wrap your console.log() within a function and call that function from within your callback.
Example:
let someVar;
someAsync('someurl.com', (data) =>{
someVar = data;
callTheConsole()
})
function callTheConsole(){
console.log(someVar)
}
Instead of assigning the value to the variable. Pass it to another function. Thus the value passed to another function is not 'undefined'.
function validation(pricecrex){
console.log(pricecrex);
}
getDataFromAPI("https://api.crex24.com/CryptoExchangeService/BotPublic/ReturnTicker?request=[NamePairs=BTC_WAGE]",
true,
function(data){
var resultcrex = JSON.parse(data);
if (resultcrex !== "undefined") {
if (resultcrex) {
var pricecrex = resultcrex.Tickers[0].Last;
validation(pricecrex);
}
else {
msg.reply("0")
}
}
}
);
For more information, check out the below link. Detailed information with examples is available.
How to return the response from an asynchronous call??

In calling URLs iteratively using http.get() and resolving using $q.all()

I am implementing this scenario where I have to fetch data from multiple URLs iteratively and process it with some business logic and display on screen. I am implementing this in the controller as it is a requirement. All is well until part-1 and I am getting the 6 promise objects in the promises array. But, I am not getting the data into metricData. I am seeing a null in the console while running in the browser. I am sure that the data is coming in the URL response. I feel I am doing something silly in the $q.all method. Is this correct?
var calculateMutationsInDepth = function(){
//Part-1
var promises=[];
var metricData=[];
for(var depth=0 ; depth<6 ; depth++){
var resourceUrl = urlService(depth);
promises.push($http.get(resourceUrl)
.then(function(response){
return response.data;
},function(status){
return status;
}));
}
//Part-2 Resolving the promise array below
$q.all(promises).then(function(data){
for(var eachResult=0; eachResult < data.length; eachResult++){
if(null != data[eachResult]){
var eachDataObject = data[eachResult];
//For debugging console.log(eachDataObject);
for(var objCount=0; objCount < eachDataObject.length; objCount++){
if(eachDataObject[objCount].scope === "PRJ" || eachDataObject[objCount].scope === "FIL")
metricData.push(eachDataObject[objCount]);
}
}
}
});
if(metricData != null){
analyzeMutationData(metricData); //Calling a function with the aggregated data array where business logic is present
}
};
calculateMutationsInDepth(); //Calling the above function
Yes, something silly.
As written, analyzeMutationData(metricData) is called synchronously whereas metricData is populated asynchronously inside the $q.all(promises).then() callback.
Also, as written the error handler function(status){ return status; } is inappropriate. Either :
omit the error handler entirely and allow any single $http error to prevent further processing in Part 2, or
return null, allowing processing in Part 2, and the if(dataObject != null) test in part 2 to filter out any such error.
Here's the revised code with a few other tidies and a demonstration of what can be done if calculateMutationsInDepth() returns a promise.
var calculateMutationsInDepth = function() {
//Part-1
var depth, promises = [];
for(depth=0; depth<6; depth++) {
promises.push($http.get(urlService(depth))
.then(function(response) {
return response.data;
}, function(error) {
return null; // error recovery - `dataObject` below will be null
}));
}
//Part-2 Aggregate the promises, extract metric data and apply business logic
return $q.all(promises).then(function(data) { // note `return` here
var dataObject, i, j, metricData = [];
for(i=0; i<data.length; i++) {
dataObject = data[i];
if(dataObject != null) {
for(j=0; j<dataObject.length; j++) {
if(dataObject[j].scope === "PRJ" || dataObject[j].scope === "FIL") {
metricData.push(dataObject[j]);
}
}
}
}
// Analyse here, inside the .then()
if(metricData.length > 0) { // metricData is an array and will never be null, therefore test metricData.length.
return analyzeMutationData(metricData);
}
return null;
});
};
calculateMutationsInDepth().then(function(analysis) {
// all complete
// `analysis` is either null or whatever `analyzeMutationData(metricData)` returned.
}).catch(function(error) {
console.log(error);
});
Hope this helps you out! Let me know if it doesn't.

Parse function time out management

In Parse Cloud Code there is a response time limit of 15s. We've been experiencing problems on certain requests that depend on external service requests.
If we have 4 promises, promise 1 & 2 create objects but if the request "runs out of time" on promise 3 we need to destroy whatever was created on the process. I'm cascading the error handling in a similar way as the following example:
var obj1, obj2, obj3;
query.find().then(function() {
obj1 = new Parse.Object('Anything');
return obj1.save();
}).then(function() {
obj2 = new Parse.Object('Anything');
return obj2.save();
}).then(function _success() {
obj3 = new Parse.Object('Anything');
return obj3.save();
}).then(function _success() {
response.success();
}, function _error(err) {
var errorPromises = [];
if (obj1 != undefined) errorPromises.push(deleteExternalStuff(obj1.id));
if (obj2 != undefined) errorPromises.push(deleteExternalStuff(obj2.id));
if (obj3 != undefined) errorPromises.push(deleteExternalStuff(obj3.id));
Parse.Promise.when(errorPromises).then(function _success() {
response.error();
}, function _error() {
response.error(err);
});
});
The deleteExternalStuff function makes a get request on one of the object's id and then returns an object.destroy() promise.
My problem is that the get query works but the destroy promises inside the deleteExternalStuff are not deleting the objects from the database. Any suggestions on how to handle this case?
EDIT:
I've tested and whenever a timeout occurs, the error IS INDEED executed but the destroy() is what is not working just right.
EDIT 2: Added a similar structure for the deleteExternalStuff function
function deleteExternalStuff(objectId) {
var query = Parse.Query('Another Object');
query.equalTo('objXXX', objectId);
return query.find().then(function _success(anotherBunchOfObjects) {
var deletePromises = _.map(anotherBunchOfObjects, function(obj) {
return obj.destroy();
});
return Parse.Promise.when(deletePromises);
}, function _error(error) {
console.log(error); // **ERROR LOG**
return Parse.Promise.as();
});
}
EDIT 3:
With further testing I added an error handler in deleteExternalStuff function and printed to log... Apparently the **ERROR LOG** prints the following: {"code":124,"message":"Request timed out"}
This makes me think that Parse doesn't permit the use of chained promises in error handling if you have already reached the timeout limit... :\
Suggestions for alternate solutions are appreciated.
To make sure all objects are deleted before your request is finished, you will have to wait until all promises are resolved:
var promises = [];
if (obj1 != undefined) promises.push(deleteExternalStuff(obj1.id));
if (obj2 != undefined) promises.push(deleteExternalStuff(obj2.id));
if (obj3 != undefined) promises.push(deleteExternalStuff(obj3.id));
Promise.all(promises).then(function() {
response.error(err);
});

require() not running synchronously?

I'm trying to load a module I created, and when it's loaded use some of it's methods. But it seems the code after the require gets executed before the require actually finishes.
Here is some code :
console.log(db);
var db = require('../../models')(true, v);
console.log(db);
Both console.log output undefined.
Here is the code inside ../../models :
module.exports = function(sync, v) {
if(sync === true && typeof v !== 'undefined') {
var db = null;
async.series([function(callback) {
require('../lib/db_connect.js').connect(require('../lib/config.js').vars.db, function(res) {
db = res;
callback();
});
}], function() {
return loadModels(db, v).models; // this returns the db instance with the models loaded
});
} else { /* other stuff */ }
});
However, I see the connection debug popping in the console some time after (so it gets loaded, just not synchronous). What am I doing wrong? async.series should return only when everything is finished? And most of all, not return undefined?

Accessing variables outside of function: JavaScript [duplicate]

this function gets a question from a database and is supposed to return it.
The database is a Parse object(https://www.parse.com/docs/js_guide). As indicated in the comments in the code the question is accessible from within the success function of the db call but not from outside it and simply putting the return statement inside the success block doesn't work either.
Code below. Any suggestions?
function getQuest(){
var Question = Parse.Object.extend("Question");
var query = new Parse.Query("Question");
var questlist = [];
var newquestion;
//get list of questions if chosen track is python or java. track is set globally
if (track == "python")
{
query.equalTo("track", "xstsysysus7");
} else if (track == "java"){
query.equalTo("track", "XAWqBgxFAP");
}
query.find({
success: function(questions){
// return list of questions
var i = Math.floor(Math.random()*10);
newquestion = questions[i].get('question');
console.log(newquestion); // works here
},
error: function(error){
console.log(error.message);
}
});
console.log(newquestion); //returns undefined here
return newquestion;
}
You cannot return from the callback method like this, this is an async issue, you should use a callback method to get your variable out from the method
function getQuest(callback){
var Question = Parse.Object.extend("Question");
var query = new Parse.Query("Question");
var questlist = [];
var newquestion;
//get list of questions if chosen track is python or java. track is set globally
if (track == "python")
{
query.equalTo("track", "xstsysysus7");
} else if (track == "java"){
query.equalTo("track", "XAWqBgxFAP");
}
query.find({
success: function(questions){
// return list of questions
var i = Math.floor(Math.random()*10);
newquestion = questions[i].get('question');
//call the callback method here and pass your variable as a param
if(callback != null && callback != undefined){
callback(newquestion);
}
},
error: function(error){
console.log(error.message);
}
});
}
Now you can call your getQuest method just like this instead of using var newQ = getQuest()
getQuest(function(newQuestion){
// do your stuff with newQuestion
})
The callbacks (success and error), are asynchronous. They have probably not been executed before your function returns.

Categories

Resources