Add callback to for loop function - javascript

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;
}
}
}
}
}

Related

I keep getting "undefined" as an error, function not returning anything

I've been trying to figure out why I keep getting undefined, and I don't really see why, I know that I would get undefined if my function isn't returning anything, but in this case, even with returning in two places, I am still getting undefined. I think that the reason for that is that maybe I am not returning the value from innerFunc properly? I'm thinking maybe there's something wrong with my syntax here: innerFunc(arg) but I'm not sure how it is wrong, or what to change it to.
Any help would be appreciated.
Instructions:
Create a function "fastCache" that takes one argument (a function) and returns a function. When fastCache is invoked it creates an object that tracks calls to the returned function, where each input to the returned function is associated with its output. Every subsequent call to that returned function with the same argument will return the output directly from the object, instead of invoking the original function again.
function fastCache(func) {
const obj = {};
function innerFunc(arg) {
for (const key in obj) {
if (key === arg) {
return obj[arg]
} else {
obj[arg] = innerFunc(arg)
return innerFunc(arg)
console.log(obj[arg])
console.log(arg)
console.log(innerFunc(arg))
}
}
}
return innerFunc
// console.log(innerFunc(arg))
}
//example:
//SINGLE ARGUMENT CASE
const multiplyBy2 = num => num * 2;
const cachedMultiplyBy2 = fastCache(multiplyBy2);
If you want a simple cache function:
function cacheWrapper(fn) {
let cache = { };
return arg => {
if (cache.hasOwnProperty(arg)) {
return cache[arg];
}
return cache[arg] = fn(arg);
};
}
function test(x) {
return x * 2;
}
let testCached = cacheWrapper(test);
console.log(testCached(2));
console.log(testCached(2));
The key here is hasOwnProperty which will tell you if that cache slot is occupied or not. This avoids having to fumble around and find out the hard way with iteration.
If the number isn't already in the object, it won't be found in the loop.
function fastCache(func) {
const obj = {};
function innerFunc(arg) {
for (const key in obj) {
if (key === arg) {
return obj[arg]
}
}
obj[arg] = func(arg)
return func(arg)
}
return innerFunc
// console.log(innerFunc(arg))
}
//example:
//SINGLE ARGUMENT CASE
const multiplyBy2 = num => num * 2;
const cachedMultiplyBy2 = fastCache(multiplyBy2);
const result = cachedMultiplyBy2(8);

Functions in javascript and scopes

Here i have simplified my problem to this code. I need to build a table. I have 3 functions(one,two,three) that have specific functionality, and i have a main function that builds a table from the return of this 3 functions. However i don't fully understand how to finish this.
function foo(one,two,three){
var result = "";
for (var i=0;i<arguments.length;i++){
result+= arguments[i](true);
result+= arguments[i](false);
}
console.log(result);
}
foo(one);
There could be 2 more functions, but in this case it doesn't matter i wrote only one. So the one() can accept 2 arguments(true or false) and
function one(arg){
if(arg == true){
this.result += "1-true";
} else if(arg ==false){
this.result += "1-false";
}
return this.result;
}
When you call a function, it won't inherit the scope from the calling code, so the property this.result in the one function won't be the same as the local variable result in the foo function.
Unless you call a function as a method of an object, the context of the function (this) will be the global window object. Inside the one function this.result will be the same as window.result. As the window object is the global context, you will create a global variable named result.
The variable result declared inside the foo function is local to that function, and it's separate from the global result variable. From the one function you can't even reach the result variable in foo function at all.
As the one function is using a global variable that is never assigned a value, it will contain undefined from the start. Adding "1-true" to it will convert undefined into the string "undefined" and the result is "undefined1-true". In the next call to one the value in the global variable is still there, so it will add "1-false" to it, making it "undefined1-true1false". As the foo function adds the values from the first and the second call to one, the result is "undefined1-trueundefined1-true1-false".
If you would use the global variable in both functions so that they used the same variable (which is what it seems that you tried to do), you would get a different result. The one function would add "1-true" to the variable and then return the variable. The foo function would then add the returned value to the variable, making it "1-true1-true". The next call to one would add "1-false" to the variable making it "1-true1-true1-false" and then return the value of the variable, which the foo function adds to the variable, making it "1-true1-true1-false1-true1-true1-false".
Instead of adding to the variable in both functions, you should just return a string from the one function, and put the strings together in the foo function:
function foo(one,two,three) {
var result = "";
for (var i = 0; i < arguments.length; i++) {
result += arguments[i](true);
result += arguments[i](false);
}
console.log(result);
}
foo(one);
function one(arg) {
if(arg == true) {
return "1-true";
} else if (arg == false) {
return "1-false";
}
}
Note: Instead of using if (arg == true) you can just use if (arg), and the else if() can just be an else:
function one(arg) {
if(arg) {
return "1-true";
} else {
return "1-false";
}
}
You can also use the conditional operator to get the same result:
function one(arg) {
return arg ? "1-true" : "1-false";
}
If you still want to use a variable in the one function, you don't need to use the += operator as you only have one string. You can just assign the value:
function one(arg) {
var result;
if(arg) {
result = "1-true";
} else {
result = "1-false";
}
return result;
}
Try to change condition for function one:
var result = '';
if (arg) { .... } else { ... };
return ...;
Thanks for suggestions, considering all the answers above i figured out the solution.
function foo(one, two,three) {
//Vehicle parts
var vhcparts = {
a: "cabin",
b: "wheel",
c: "body",
d: "trail",
e: "back",
f: "doublewheel",
g: "triplewheel",
h: "fourwheel",
i: "aftercabin",
j: "bodybegin"
}
//Final image string + 2chars, to add extra space at front and back;
var imageDescription = "aijbcccccccge" // obj.imageDescription;
imageDescription = "-" + imageDescription + "-";
//Iterate throught list of arguments to build specific line of TruckMainBoard
var result = "";
for (var i = 0; i < arguments.length; i++) {
result += "<tr>";
//Iterate throught image string to generate td and populate it
for (var j=0;j<imageDescription.length;j++){
// Verify if imageDescription string matches vhcparts(vehicle parts) array.
for (var p in vhcparts){
// var counter = 0;
if(imageDescription[j] == p
&&
(imageDescription[j] == "a" ||
imageDescription[j] == "b" ||
imageDescription[j] == "f" ||
imageDescription[j] == "g" ||
imageDescription[j] == "h"
)
)
{
result += arguments[i](true);
}
else if(imageDescription[j] == p) {
result += arguments[i](false);
}
}
}
result += "</tr>"
}
console.log(result);}
function one(arg){
var result = "";
if(arg){
result += '<td><img src="images/';
//result += vhcparts[p];
result +='.png">';
result +='</td>';
} else {
console.log("nothing to print")
}
return result;
}
foo(one,two);

Why does this forEach return undefined when using a return statement

Object.prototype.e = function() {
[].forEach.call(this, function(e) {
return e;
});
};
var w = [1,2];
w.e(); // undefined
But this works if I use alert instead
// ...
[].forEach.call(this, function(e) {
alert(e);
});
// ...
w.e(); // 1, 2
I realize this is an old question, but as it's the first thing that comes up on google when you search about this topic, I'll mention that what you're probably looking for is javascript's for.. in loop, which behaves closer to the for-each in many other languages like C#, C++, etc...
for(var x in enumerable) { /*code here*/ }
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Statements/for...in
http://jsfiddle.net/danShumway/e4AUK/1/
A couple of things to remember :
for..in will not guarantee that your data will be returned in any particular order.
Your variable will still refer to the index, not the actual value stored at that index.
Also see below comments about using this with arrays.
edit: for..in will return (at the least) added properties to the prototype of an object. If this is undesired, you can correct for this behavior by wrapping your logic in an additional check:
for(var x in object) {
if(object.hasOwnProperty(x)) {
console.log(x + ": " + object[x]);
}
}
Your example is a bit odd, but as this question is becoming the canonical "return from forEach" question, let's use something simpler to demonstrate the problem:
Here, we have a function that checks the entries in an array to see if someProp matches value and, if so, increments the count on the entry and returns the entry:
function updateAndReturnMatch(array, value) {
array.forEach(function(entry) {
if (entry.someProp == value) {
++entry.count;
return entry;
}
});
}
But calling updateAndReturnMatch gives us undefined, even if the entry was found and updated.
The reason is that the return inside the forEach callback returns from the callback, not from updateAndReturnMatch. Remember, the callback is a function; return in a function returns from that function, not the one containing it.
To return from updateAndReturnMatch, we need to remember the entry and break the loop. Since you can't break a forEach loop, we'll use some instead:
function updateAndReturnMatch(array, value) {
var foundEntry;
array.some(function(entry) {
if (entry.someProp == value) {
foundEntry = entry;
++foundEntry.count;
return true; // <== Breaks out of the `some` loop
}
});
return foundEntry;
}
The return true returns from our some callback, and the return foundEntry returns from updateAndReturnMatch.
Sometimes that's what you want, but often the pattern above can be replaced with Array#find, which is new in ES2015 but can be shimmed for older browsers:
function updateAndReturnMatch(array, value) {
var foundEntry = array.find(function(entry) {
return entry.someProp == value;
});
if (foundEntry) {
++foundEntry.count;
}
return foundEntry;
}
The function e() isn't returning anything; the inner anonymous function is returning its e value but that return value is being ignored by the caller (the caller being function e() (and can the multiple uses of 'e' get any more confusing?))
Because
function(e) {
return e;
}
is a callback. Array.forEach most likely calls it in this fashion:
function forEach(callback) {
for(i;i<length;i++) {
item = arr[i];
callback.call(context, item, i, etc.)
}
}
so the call back is called, but the return doesn't go anywhere. If callback were called like:
return callback.call();
the it would return out of forEach on the first item in the array.
You can use for...of to loop over iterable objects, like array, string, map, set... as per Mozilla docs.
const yourArray = [1, 2, 3]
for (const el of yourArray) { // or yourMap, Set, String etc..
if (el === 2) {
return "something"; // this will break the loop
}
}

How to return values in javascript

I have a javascript function:
function myFunction(value1,value2,value3)
{
//Do stuff and
value2=somevalue2 //to return
value3=somevalue3 //to return
}
function call in Code:
....
myFunction("1",value2,value3);
if(value2 && value3)
{
//Do some stuff
}
in this scenario how to pass value2 and value3 to the called method or how to return values in Java script.
You can return an array, an object literal, or an object of a type you created that encapsulates the returned values.
Then you can pass in the array, object literal, or custom object into a method to disseminate the values.
Object example:
function myFunction(value1,value2,value3)
{
var returnedObject = {};
returnedObject["value1"] = value1;
returnedObject["value2"] = value2;
return returnedObject;
}
var returnValue = myFunction("1",value2,value3);
if(returnValue.value1 && returnValue.value2)
{
//Do some stuff
}
Array example:
function myFunction(value1,value2,value3)
{
var returnedArray = [];
returnedArray.push(value1);
returnedArray.push(value2);
return returnedArray;
}
var returnValue = myFunction("1",value2,value3);
if(returnValue[0] && returnValue[1])
{
//Do some stuff
}
Custom Object:
function myFunction(value1,value2,value3)
{
var valueHolder = new ValueHolder(value1, value2);
return valueHolder;
}
var returnValue = myFunction("1",value2,value3);
// hypothetical method that you could build to create an easier to read conditional
// (might not apply to your situation)
if(returnValue.valid())
{
//Do some stuff
}
I would avoid the array method because you would have to access the values via indices rather than named object properties.
Javascript is duck typed, so you can create a small structure.
function myFunction(value1,value2,value3)
{
var myObject = new Object();
myObject.value2 = somevalue2;
myObject.value3 = somevalue3;
return myObject;
}
var value = myFunction("1",value2,value3);
if(value.value2 && value.value3)
{
//Do some stuff
}
function myFunction(value1,value2,value3)
{
return {val2: value2, val3: value3};
}
It's difficult to tell what you're actually trying to do and if this is what you really need but you might also use a callback:
function myFunction(value1,callback)
{
//Do stuff and
if(typeof callback == 'function'){
callback(somevalue2,somevalue3);
}
}
myFunction("1", function(value2, value3){
if(value2 && value3)
{
//Do some stuff
}
});
I would prefer a callback solution:
Working fiddle here: http://jsfiddle.net/canCu/
function myFunction(value1,value2,value3, callback) {
value2 = 'somevalue2'; //to return
value3 = 'somevalue3'; //to return
callback( value2, value3 );
}
var value1 = 1;
var value2 = 2;
var value3 = 3;
myFunction(value1,value2,value3, function(value2, value3){
if (value2 && value3) {
//Do some stuff
alert( value2 + '-' + value3 );
}
});
The return statement stops the execution of a function and returns a value from that function.
While updating global variables is one way to pass information back to the code that called the function, this is not an ideal way of doing so. A much better alternative is to write the function so that values that are used by the function are passed to it as parameters and the function returns whatever value that it needs to without using or updating any global variables.
By limiting the way in which information is passed to and from functions we can make it easier to reuse the same function from multiple places in our code.
JavaScript provides for passing one value back to the code that called it after everything in the function that needs to run has finished running.
JavaScript passes a value from a function back to the code that called it by using the return statement. The value to be returned is specified in the return keyword.
Its very simple. Call one function inside another function with parameters.
function fun1()
{
var a=10;
var b=20;
fun2(a,b); //calling function fun2() and passing 2 parameters
}
function fun2(num1,num2)
{
var sum;
sum = num1+num2;
return sum;
}
fun1(); //trigger function fun1
The answers cover things very well. I just wanted to point out that the mechanism of out parameters, as described in the question isn't very javascriptish. While other languages support it, javascript prefers you to simply return values from functions.
With ES6/ES2015 they added destructuring that makes a solution to this problem more elegant when returning an array. Destructuring will pull parts out of an array/object:
function myFunction(value1)
{
//Do stuff and
return [somevalue2, sumevalue3]
}
var [value2, value3] = myFunction("1");
if(value2 && value3)
{
//Do some stuff
}

javascript, wait for something to be true then run action

Well the title kindof says what I need. Because in Javascript timeouts asynchronous I need to know when something becomes true. I don't want busyloop.
Came up with:
function do_when(predicate, action, timeout_step) {
if (predicate()) {
action();
} else {
setTimeout(do_when, timeout_step, predicate, action, timeout_step);
}
}
Is it good Javascript or can I make better?
Depending on what the predicate is, you might be able to fit your problem into an implementation of the observer pattern. A while back I wrote a blog post about creating JavaScript objects with observable properties. It really depends on what the predicate is, but this might get you most of the way there with code like this:
var observable = createObservable({ propToWatch: false });
observable.observe('propToWatch', function (oldValue, newValue) {
alert('propToWatch has changed from ' + oldValue + ' to ' + newValue);
});
observable.propToWatch(true); // alert pops
Of course, this might be overkill for your example. Since it's never listed out explicitly (n.b. I am not a very good blogger), here's the complete code needed to make this work:
var createMediator = function () {
var events = {};
return {
subscribe: function (eventName, callback) {
events[eventName] = events[eventName] || [];
events[eventName].push(callback);
},
publish: function (eventName) {
var i, callbacks = events[eventName], args;
if (callbacks) {
args = Array.prototype.slice.call(arguments, 1);
for (i = 0; i < callbacks.length; i++) {
callbacks[i].apply(null, args);
}
}
}
};
};
var createObservable = function (properties) {
var notifier = createMediator(), createObservableProperty, observable;
createObservableProperty = function (propName, value) {
return function (newValue) {
var oldValue;
if (typeof newValue !== 'undefined' &&
value !== newValue) {
oldValue = value;
value = newValue;
notifier.publish(propName, oldValue, value);
}
return value;
};
};
observable = {
register: function (propName, value) {
this[propName] = createObservableProperty(propName, value);
this.observableProperties.push(propName);
},
observe: function (propName, observer) {
notifier.subscribe(propName, observer);
},
observableProperties: []
};
for (propName in properties) {
observable.register(propName, properties[propName]);
}
return observable;
};
My observable objects make use internally of a small eventing framework (the createMediator function) I wrote once for a project. (Before realizing jQuery supported custom events. D'oh!) Again, this may or may not be overkill for your need, but I thought it was a fun hack. Enjoy!
It's decent enough, if it's easy enough to read and it works just fine then it's generally good javascript.
Performance-wise, it's generally better to call the function whenever whatever is set to true happens. So in whatever function that executes to make predicate() return true, you could just call action() at the end. But I'm sure that's what you would have done if you could, right?
You could also look at using a callback, where you register a javascript function to a particular variable or function argument and when the function is run it executes whatever function was set to the callback variable.
if your predicate become true when a variable change, here is another solution:
say we want to log 'Big brother is watching you' when value of object a become 2.
function observable (value, condition, callback){
this.value = value;
this.condition = condition;
this.callback = callback;
}
observable.prototype = {
get value () {
return this._value;
},
set value (value) {
this._value = value;
if (this.condition && this.callback && this.condition (value)) {
this.callback (value);
}
}
};
condition = function (value) {
console.log ('condition', value);
return value === 2;
}
callback = function (value) {
console.info ('Big Brother is watching you!');
}
var a = new observable (0, condition, callback);
console.log ('set value to 1');
a.value = 1;
console.log ('set value to 2');
a.value = 2;
console.log ('set value to 3');
a.value = 3;
you can try this exemple in firefox

Categories