function returns undefined while log shows result - javascript

I want to call a function inside a loop.
This function returns undefined, while the log shows me the correct output in the function.
Where i call the function:
function getAllFilters(allFilters){
var allFiltersWithCount =[]
allFilters.forEach(function(item){
if(item.name != null || typeof(item.name) != 'undefined') {
allFiltersWithCount.push(function (callback){
console.log("inloop" + getFiltersByFilterCategory(item.name) );
callback(null,getFiltersByFilterCategory(item.name));
});
}
});
async.parallel(allFiltersWithCount, function(err, result) {
console.log("results " + result);
return allFiltersWithCount;
});
}
And a part of the function i'm calling:
function getFiltersByFilterCategory(filterCategory){
switch(filterCategory){
case "prescription":
ProductSchema.aggregate(
{
$group:
{_id: '$prescription', total: {$sum:1}}
},
function(err,res){
var toreturn = {name:"prescription",filters: sort(res)};
console.log(toreturn);
return toreturn;
})
case "usage": {...}
in my log I see:
inloopundefined (multiplied by the number of loops)
results ,,,,,
{ name: 'prescription',
filters:
[{...},{...},...]
So I'm guessing it runs this function async. But how does javascript let me do this correctly and what is really happening? Does he returns the function to early, and then just do the console.log afterwards? Or what?

Assuming the getFiltersByFilterCategory function is defined on the window object (defined on the global scope). The undefined is logging because the function is ultimately being called with a context that is not window, so to fix this you can declare the function as a variable within the closure where it's still within scope.
I.e. Below, (obviously a cleaner solution would be restructured.)
function getAllFilters(allFilters){
var allFiltersWithCount =[];
var getFiltersByFilterCategory = function(name){ };
allFilters.forEach(function(item){
if(item.name != null || typeof(item.name) != 'undefined') {
allFiltersWithCount.push(function(callback){
console.log("inloop" + getFiltersByFilterCategory(item.name));
callback(null,getFiltersByFilterCategory(item.name));
});
}
});

Related

How to make sure that the variable is not null while using promise chaining approach?

I am using init as follows
$scope.init = function () {
$scope.getAllDetails();
};
$scope.getAllDetails= function () {
$http({
method: "GET",
url: "api/endpoint"
}).then(function mySuccess(response) {
$scope.processData();
}, function myError(response) {
console.log(response.statusText);
}
);
};
$scope.processData() = function() {
//Logic to calculate var1
// var1 is then passed to $scope.getID to make call to Service1.getId(var1)
}
I have my first function which returns a promise:
$scope.getID = function() {
return Service1.getId("abc").then(function(response){
// In above line. Instead of manually passing `abc` I want to
//pass it as variable var1
// The desired call should be as below.
//But var1 is having null here
//return Service1.getId(var1).then(function(response){
$scope.genewtId = response.data[0].Id;
console.log($scope.genewtId);
return response.data[0].Id;
}, function(error){
console.log(error.statusText);
throw error;
});
};
The second function returns a promise and accept an argument:
$scope.getDetails = function(id) {
var genewtID = id || $scope.genewtId;
return Service2.getDetails(genewtId).then(function(response){
$scope.data1 = response.data;
console.log($scope.data1.toString());
return response.data;
}, function(error){
console.log(error.statusText);
throw error;
});
};
Then chaining the two promises:
var promise = $scope.getId();
var promise2 = promise.then(function(id) {
return $scope.getDetails(id);
});
var promise2.then(function(data) {
console.log(data);
}).catch(function(error) {
console.log(error);
});
Problem:
The problem I am facing is related to var1 in $scope.processData()
The var1 is always having null value within $scope.getID
the var1 value is undefined
Sounds like this could be a problem with closures. A function will have access to the containing closures of the code where it was defined, not where it is called.
Is var1 truly null, or is it in fact undefined? If it's undefined, probably what you need to do is make getId take var1 as an argument instead of relying on pulling the reference from the containing closure (which will not work for the reason stated above). If it's truly null, then the problem probably lies in the code that calculates var1, which you've omitted.
EDIT: The getID() function would look very similar, but it would start like this:
$scope.getID = function(var1) {
Instead of this:
$scope.getID = function(var1) {
And to call it you would probably do something like this:
var var1 = somethingToGetTheValueOfVar1();
$scope.getID(var1);
The problem I am facing is related to var1 in $scope.processData() The var1 is always having null value within $scope.getID the var1 value is undefined
Add var1 as a parameter to the function definition:
̶$̶s̶c̶o̶p̶e̶.̶g̶e̶t̶I̶D̶ ̶=̶ ̶f̶u̶n̶c̶t̶i̶o̶n̶(̶)̶ ̶{̶
$scope.getID = function(var1) {
//return Service1.getId("abc").then(function(response){
// In above line. Instead of manually passing `abc` I want to
//pass it as variable var1
// The desired call should be as below.
//But var1 is having null here
return Service1.getId(var1).then(function(response){
$scope.genewtId = response.data[0].Id;
console.log($scope.genewtId);
return response.data[0].Id;
}, function(error){
console.log(error.statusText);
throw error;
});
};
I am trying to call the function as following but it is not working
$scope.processData() = function() { ... $scope.getID(var1); }
The left-hand side of an assignment statement must be a variable or property accessor.
$̶s̶c̶o̶p̶e̶.̶p̶r̶o̶c̶e̶s̶s̶D̶a̶t̶a̶(̶)̶ ̶=̶ ̶f̶u̶n̶c̶t̶i̶o̶n̶(̶)̶ ̶{̶ ̶
$scope.processData = function(data) {
//...
var var1 //= something
return $scope.getID(var1);
}
Then be sure to chain properly:
$scope.getAllDetails= function () {
return $http({
method: "GET",
url: "api/endpoint"
}).then(function mySuccess(response) {
var data = response.data;
return $scope.processData(data);
}, function myError(response) {
console.log(response.statusText);
//IMPORTANT RE-THROW error
throw response;
});
};
It is important to return values to .then blocks. Otherwise the new promise will resolve as undefined.
Also it is important to throw from .catch blocks. Otherwise the new promise will be converted from a rejected promise to a fulfilled promise.
For more information, see
You're Missing the Point of Promises

return javascript variable from inside callback function

I am trying to get client.get to return the reply value so it can be used globally.It keeps saying undefined.any suggestions
var redis = require("redis");
var websocket= require("websocket");
var valuewanted;
websocket.on('message', function(data) {
if (data.type == "purchase" && data.price > 0) {
console.log("==========================================================");
console.log(data );
console.log("==========================================================");
client.get(p1, function(err, reply) {
var valuewanted = reply;
console.log(reply);
});
});
the console.log logs the value but if i try to log valuewanted it doesnt work.
Drop the var within the client.get function:
client.get(p1, function(err, reply) {
// valuewanted already defined above
valuewanted = reply;
console.log(reply);
});
If you use var within a function, it becomes scope-blocked to that function.
From mozilla:
The scope of a variable declared with var is its current execution
context, which is either the enclosing function or, for variables declared outside any function, global.
In this case, using var within that function redefines it within that function, and its scope becomes "the enclosing function". Hope this helps.

Add callback to for loop function

I have a function to which I pass an array or an object, then it looks for specific keys and edits their values accordingly,
function iterate(obj, delta) {
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
if (typeof obj[property] == "object") {
iterate(obj[property],delta);
} else {
if(property === 'unix_time'){
var bee = parseInt(obj[property]);
var b = bee + parseInt(delta);
obj[property] = b;
}
}
}
}
}
Basically, it looks for the "unix_time" key and add a number "delta" to it.
Question: When I call it asynchronous, it becomes undefined, How can I add a callback that I can simply use to determine that the function has finished executing. Or maybe should I add a promise to it?
For example when i run this it returns perfectly
console.log("new one", obj);
iterate(obj, 3600000)
But this is a problem, it becomes undefined
var dd = iterate(obj, 3600000);
res.status(200).send(JSON.stringify(dd));
As mentioned in comments, you function is synchronous and it returns immediately after you call it like this:
var result = iterate(tree, delta);
However, as it's currently written, the result variable will have value of undefined since your iterate function doesn't return anything.
If you have the setup like this:
var obj = {...};
iterate(obj, 3600000)
console.log(obj) // correctly outputs modified object
It will output modified object, since you're not using here the returned value from the function. However, in this scenario:
console.log("new one", iterate(obj, 3600000)); // ouputs `undefined`
the returned value is used and it's undefined.
Using the use case you provided, you can modify the usage like this:
iterate(obj, 3600000);
res.status(200).send(JSON.stringify(obj));
and it will work fine. Or you need to modify iterate to return value. Provide an example of obj so I can write a modification to your iterate function.
Modified the iterate function:
function iterate(obj, delta) {
obj.forEach(function (element) {
if (element.hasOwnProperty('unix_time')) {
element['unix_time'] = parseInt(element['unix_time']) + parseInt(delta);
}
});
return obj;
}
I don't know I understand your question. But, if you want to use a callback, you should split this funcion in two. One for main operation and another for recursivity.
i.e.
function iterate(obj, delta, callback) {
interate_recursive(obj, delta);
if(typeof callback != 'undefined')
return callback();
else return obj;
}
function interate_recursive(obj,delta){
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
if (typeof obj[property] == "object") {
iterate(obj[property],delta);
} else {
if(property === 'unix_time'){
var bee = parseInt(obj[property]);
var b = bee + parseInt(delta);
obj[property] = b;
}
}
}
}
}

How to invoke a function, as a "new Object", and call as a function again?

As a learning experience, I'm trying to make my own little console debug script that is object-oriented. I want it to be similar to jQuery in that you can call it as a function (jQuery('div')) or as an object (jQuery.ajax()).
I have the code below which is almost working. It is basically an alias of "console.log".
My goal is to be able to perform the following:
var log = new RadDebug;
// Create our function
log('You selected: %s', fruit_type);
// Invoke the top-level function
// Output: You selected: "Apple"
log.warn('You selected: %s', fruit_type);
// Invoke a method "warn", which displays a caution icon next to the log.
// Output: (!) You selected "Apple"
The script I am working on:
function RadDebug() {
var debug_enabled = (debug_mode && window.console && window.console.log instanceof Function);
// If this object was already initialize, redirect the function call to the ".log()" as default
if ( this.initialized ) {
return this.log.apply( this, arguments );
}
this.initialized = true;
this.log = function() {
if ( !debug_enabled ) return;
console.log.apply( console, arguments );
};
this.info = function() {
if ( !debug_enabled ) return;
console.info.apply( console, arguments );
};
// More methods below
}
The problem:
Calling log.warn("hello world") works as you would expect.
Calling log("hello world") tells me that TypeError: Object is not a function.
Question: How do I get it to work as a function and having object-like properties? (Like how jQuery does it)
(This question has been resolved thanks to #FelixKling. The final code is available as a Gist if you want to check it out).
Don't use RadDebug as constructor function, just attach the methods to the function itself.
For example:
var RadDebug = (function() {
// Some IIFE to keep debug_enabled and functions local
var debug_enabled = (debug_mode && window.console && window.console.log instanceof Function);
// Functions here
function log() {
if ( !debug_enabled ) return;
console.log.apply( console, arguments );
}
function info() {
if ( !debug_enabled ) return;
console.info.apply( console, arguments );
}
// ...
// Attach methods to "main" log function
log.log = log;
log.info = info;
// ...
// Return log function (RadDebug === log)
return log;
}());
Then you use it as
RadDebug('You selected: %s', fruit_type);
// same as
RadDebug.log('You selected: %s', fruit_type);
RadDebug.info('You selected: %s', fruit_type);
or alias RadDebug to whatever you want (e.g. log).
Functions are Objects in Javascript. You can return a function in your RadDebug function and set one of its members to the same returned function. For example:
var hello = function () {
var fn = function () {
console.log("Hello");
}
fn.hello = fn;
return fn;
}
var sayHello = new hello();
sayHello(); // prints "Hello"
sayHello.hello(); // prints "Hello"

Chrome Extension/Javascript: Variable still undefined

I didn't really understand the callback function, and this might be the source of the problems I got:
I have a getCookies() function and it worked, but now I moved it in the background.js and the variable outside the function is still undefined.
Just take a look:
function getCookies(domain, name, callback) {
chrome.cookies.get({"url": domain, "name": name}, function(cookie) {
if(callback) {
callback(cookie ? cookie.value : null);
}
});
}
var upw; //Passwort HASH
//USER PW Hash auslesen
getCookies("http://example.org/", "upw", function(id) {
if(id == null) {
upw= null;
}
else { upw = id;}
console.log("Func: "+upw);
});
console.log("Outside: "+upw);
The console will give me something like this:
Outside: undefined
Func: 1234asdfqwertz5678
So the function will be exectued "too late". I don't know why and I don't know, how to solve this question!
The callback function is asynchronous, so it can't work! I'm handling everything in the Callback function.

Categories