I have a function that takes an array, performs some operations and returns a number. Here's a truncated version:
function similarity(phrases){
if(phrases.length ==2){
//Lots of stuff
//concerning the phrases happen here
// and a variable called similarity is produced which
//contains a number
return similarity;
}else{
throw "Can only find similarity between 2 phrases";
}
}
If I call this function separately it works perfectly. If, however I try to use it inside setInterval, it throws an error.
setInterval(function(){console.log(similarity(["test","test"]))},2000);
The expected outcome is "1.00000" every 2 seconds. Instead, "1.00000" is printed once and then this error is thrown:
"setInterval(function(){console.log(similarity(["test","test"]))},2000);
TypeError:String is not a function"
(pointing to the "s" on similarity).
Any ideas on what the problem is?
Thanks a lot!
Looks like you're saving function result in variable called same way as function (similarity). This way you are overriding function from upper scope.
Try this:
function similarity(phrases) {
var similarity;
/* ... */
}
Related
I am reviewing a sample nodejs server code, which is working fine. but could not understand the following code:
var handlers = {};
// Creating a sample handler
handlers.sample = function(data,callback){
callback(406,{'name':'sample handler'}); // How is this line of code working??
};
// Creating a not found handler
handlers.notFound = function(data,callback){
callback(404); // How is this line of code working??
};
In the entire code there is no implementation of "callback" function then how
callback(406,{'name':'sample handler'});
and
callback(404);
are working?
Please suggest. Thanks.
callback isn't implemented in the code you posted; it's a named parameter.
To call one of the functions that requires a callback, you'll need to pass it in as an argument, like:
handlers.sample("some data", () => console.log("I'm in a callback!));
The first argument ("some data") goes in the data parameter, and the second argument (() => console.log("I'm in a callback!)) goes in the callback parameter. When callback(404) is run, it executes the callback function (in the above example, it would do console.log("I'm in a callback!)).
Basically, when you call handlers.sample, you should pass a function as your second argument, and that function will be called, usually asynchronously, and presumably after something is done with the data you pass as the first argument. For example, based on the code you provided:
handlers.sample(dataObject, (number, object) => {
console.log(number)
console.log(object.name)
})
would yield this result in the console:
406
sample handler
I’m curious if this is a public library you are seeing this code in, so we can take a closer look?
I did a further digging in into this and found that
selectedHandler
in the following code (this is not mentioned in the question) is getting resolved into handlers.sample or handlers.notFound variable names based on some logic (which is not mentioned here)
selectedHandler(data,function(status,payloadData){
// somelogic with the status and payloadData
});
And second parameter of this function which is a complete function in itself
function(status,payloadData){
// somelogic with the status and payloadData
}
is going as the second parameter in handlers.sample or handlers.notFound which is a Callback. So execution of Callback in the current context is execution of this function (this function is anonymous because it has no name and getting executed as Callback)
Task: I need to recursively walk through a json object and make certain changes to the keys. I will be handling objects with varying depths, and varying sizes. When the function hits a key whose value is an object, it is called again on that object.
Problem 1.: Doing this as a synchronous function, I noticed that large json objects were returning incomplete. Using the the async library, async.forEach solves the problem of handling long tasks and returning only when finished, but...
Problem 2.: It seems that the async function loses concurrency (?) when it is called recursively (pointed out in the code snippet).
To test this idea, I removed the recursive function call and it worked (but without recursion), and I got a callback. When I add the function call back in, I get TypeError: results is not a function .
This leads me to think that async with callback and recursive functions don't mix in node. Is there a way to achieve both?
Possible Fix: I could run a separate function to count all the keys and use a counter as my control in a simple for loop, rather than letting forEach handle the control. That seems a bit inefficient, no?
Here's the code:
function fixJsonKeys(obj, results) {
async.forEach(Object.keys(obj), function(key, callback) {
if (typeof obj[key] == 'object') {
// do stuff to json key, then call the function
// on the nested object
fixJsonKeys(obj[key]);
callback(); // <-- how does this work with recursion??
}
else {
// do stuff to json key
callback();
}
}, function(err) {
if (err) return next(err);
// obj keys fixed, now return completed object
results(obj);
});
}
EDIT: hard to format in comments, so:
#Laksh and #Suhail: I tried your suggestions and same outcomes. If I remove the callback from the if condition, the async.forEach still looks to confirm that it has handled the top level keys (I think).
For example, say I have 3 top level keys, and one of them has a nested object:
[key1] (no callback, do recursion)
--[subKey1]
--[subKey2]
[key2] (callback)
[key3] (callback)
async.forEach is still looking for a callback on action taken for key1. Do I have this correct?
Since you are using recursive functions here, you don't need to call callback() inside the if condition.
This is because your recursive call will return to the existing callback() in if once the entire recursive stack finished for that particular obj[key].
Recursive function return only when the base condition is true, in your case when if condition fails so it will automatically call callback() from else block.
I am trying to work with node.js and node-java and trying to get my head wrapped around some concepts, and in particular how to write async method calls.
I think that, for a function in Java, myclass.x():
[In Java]:
Z = myclass.x(abc);
And:
[In node.js/node-java]:
myclass.x(abc, function(err,data) {
//TODO
Z = data;});
In other words, the myclass.x function gets evaluated using the parameter abc, and if no error, then the result goes into "data" which is then assigned to Z.
Is that correct?
Here's the thing (or one of the things) that I am confused about.
What happens if the function myclass.x() doesn't take any parameters?
In other words, it is normally (in Java) just called like:
Z = myclass.x();
If that is the case, how should the node.js code look?
myclass.x(, function(err,data) {
//TODO
Z = data;});
doesn't seem right, but:
myclass.x( function(err,data) {
//TODO
Z = data;});
also doesn't seem correct.
So what is the correct way to code the node.js code in this case?
Thanks in advance!!
Jim
EDIT 1: Per comments, I'm adding the specific code I'm working with is the last couple of commented out lines from this other question at:
node.js and node-java: What is equivalent node.js code for this java code?
These are the lines (commented out in that other question):
var MyFactoryImplClass = java.import("oracle.security.jps.openaz.pep.PepRequestFactoryImpl.PepRequestFactoryImpl");
var result = myFactoryImplClass.newPepRequest(newSubject, requestACTIONString ,requestRESOURCEString , envBuilt)
I tried to make the last line use an async call:
MyFactoryImplClass.getPepRequestFactory( function(err,data) {
//TODO
pepReqF1=data;})
javaLangSystem.out.printlnSync("Finished doing MyFactoryImplClass.getPepRequestFactory() and stored it in pepReqF1 =[" + pepReqF1 + "]");
But the output was showing the value of that pepReqF1 as "undefined".
If calling the method with one parameter and a callback is:
myclass.x(abc, function(err, data) {
// ...
});
Then calling a method with only a callback would be:
myclass.x(function(err, data) {
// ...
});
The function(err, data) { } part is just a normal parameter just like abc. In fact, you can pass a named function with:
function namedFun(err, data) {
// ...
}
myclass.x(abc, namedFun);
Or even:
var namedFun = function (err, data) {
// ...
}
myclass.x(abc, namedFun);
Functions in JavaScript are first-class objects like strings or arrays. You can pass a named function as a parameter to some other function:
function fun1(f) {
return f(10);
}
function fun2(x) {
return x*x;
}
fun1(fun2);
just like you can pass a named array:
function fun3(a) {
return a[0]
}
var array = [1, 2, 3];
fun3(array);
And you can pass an anonymous function as a parameter:
function fun1(f) {
return f(10);
}
fun1(function (x) {
return x*x;
});
just like you can pass an anonymous array:
function fun3(a) {
return a[0]
}
fun3([1, 2, 3]);
There is also a nice shortcut so that instead of:
fun1(function (x) {
return x*x;
});
You can write:
fun1(x => x*x);
Making my comment into an answer...
If the issue you're experiencing is that Z does not have the value you want when you are examining it, then that is probably because of a timing issue. Asynchronous callbacks happen at some unknown time in the future while the rest of your code continues to run. Because of that, the only place you can reliably use the result passed to the asynchronous callback is inside the callback itself or in some function you would call from that function and pass it the value.
So, if your .x() method calls it's callback asynchronously, then:
var Z;
myclass.x( function(err,data) {
// use the err and data arguments here inside the callback
Z = data;
});
console.log(Z); // outputs undefined
// you can't access Z here. Even when assigned
// to higher scoped variables because the callback has not yet
// been called when this code executes
You can see this is a little more clearly by understanding the sequencing
console.log('A');
someAsyncFucntion(function() {
console.log('B');
})
console.log('C');
This will produce a log of:
A
C
B
Showing you that the async callback happens some time in the future, after the rest of your sequential code has executed.
Java, on the other hand, primarily uses blocking I/O (the function doesn't return until the I/O operation is copmlete) so you don't usually have this asynchronous behavior that is standard practice in node.js. Note: I believe there are some asynchronous capabilities in Java, but that isn't the typical way things are done and in node.js, it is the typical ways things are done.
This creates a bit of an architectural mismatch if you're trying to port code that uses I/O from environment from another because the structure has to be redone in order to work properly in a node.js environment.
see codes below:
define(["dep1"], function (dep1, next) {
// necessary works here so that `dep2` is ready
// kind of circular dependency.
someNecessaryWork();
require(["dep2"], function (dep2) {
// return value in node-style, using `next()`
next(someValue);
}
// do not return value as normal, no `return someValue` here
}
Is require.js able to do this? For now I'm using functions to achieve this.
define(["dep1", "dep2Fn"], function (dep1, dep2Fn) {
someNecessaryWork();
dep2Fn();
return someValue;
});
but it feels not intuitive.
define does not allow you to set the return value of a module through a callback. What you show in your second snippet is how you do it. You just have to get used to it.
I was trying to solve the "Juggling Async" problem in the "learnyounode" workshop from nodeschool.io. I saw a lot of questions here about this problem where it is not working because the url's were being called from a loop. I understand why that wouldn't work.
I had tried something like this.
var http=require('http');
console.log(process.argv[2],process.argv[3],process.argv[4]);
fn(process.argv[2],
fn(process.argv[3],
fn(process.argv[4])));
function fn(url,callback){
http.get(url,function(response){
var string='';
response.setEncoding('utf8');
response.on('data',function(data){
string+=data;
});
response.on('end',function(){
console.log(url,string);
if (callback) {
callback();
}
});
});
};
As per my understanding, the second GET call should go out only after the first one has ended, since it is being initiated after response end. But the output is always in different order.
I have seen the correct solution. I know that doing it this way fails to leverage the advantage of async, but shouldn't the callbacks make it output in order?
When you pass in a function as a callback, you need to only pass in the function name or function definition. By providing the arguments, you are actually calling the function.
E.g. let's say you had a function f1 that took in another function as a parameter, and another function f2 that you want to pass into f1:
function f1(func_param) {
console.log('Executing f1!');
}
function f2(a_param) {
console.log('Executing f2!');
}
When you do the following call (which is similar to what you are doing, providing a callback function and specifying parameters for the callback):
f1(f2(process.argv[2]));
You're evaluating f2 first, so 'Executing f2!' will print first. The return of f2 will get passed as a parameter into f1, which will execute and print 'Executing f1!'
In your call
fn(process.argv[2],
fn(process.argv[3],
fn(process.argv[4])));
You are saying, let's pass the result of fn(process.argv[4]) as a callback to fn(process.argv[3]), and we'll get the result of calling that and pass that as a callback to fn(process.argv[2]).