I am working with node-red and I would like to create my custom function to access some index from the incoming message. The incoming message looks like this
{ "node": "02010101", "base64": "Cro=" }
It comes out from the json function block in node-red (A function that parses the msg.payload to convert a JSON string to/from a javascript object. Places the result back into the payload), I can use the debug block to obtain the index base64, however if I try to do the same with my own function to proces that later, I cannot and I get the error
TypeError: Cannot assign to read only property '_msgid' of Cro=
My function is really silly for now it is just
return msg["base64"];
I understand that it complains that there is no property in the incoming message, so I would like to access to hat index, how can I do it?
EDIT: if I set the debug block to show the whole message object not just the msg.base64 itself, I get this
{ "node": "02010101", "base64": "Cro=", "_msgid": "6babd6e.f945428" }
A function node should return a whole msg object not just a string.
If you want to just send on the string value you should do something like this:
msg.payload = msg.payload["base64"];
return msg
THe solution was easy, just return the whole message and not just a field. Using the following snippet made it work.
Getting decrypted module
msg.payload = msg.decrypted;
return msg;
base64Decode
msg.payload = msg.base64;
return msg;
Related
how to handle JSON response, I got this response but I don't know how to handle it. I know variable can't started with numbers, so?
let result = [{"1d":{"volume":"22275409068573.73","price_change":"56446.71564507","price_change_pct":"0.0121","volume_change":"-13864857829188.44","volume_change_pct":"-0.3836","market_cap_change":"9216448958327.75","market_cap_change_pct":"0.0121"}}];
How to parsing"1d"?
I try JSON.parse(result[0].1d); but error happened
If you don't want to use ["prop"] to get value, you can change all props that starts with a number like in the example.
Check this link
var json = JSON.stringify(result);
json = json.replace(/,"[0-9]|{"[0-9]/g, function (x) {
return x.substring(0,1)+'"num'+x.substring(2);
});
result = JSON.parse(json);
var whatIwant = result.num1d;
You can't use JSON.parse for JSON object.
If you want to get value of 1d. Try this
result[0]["1d"]
Propose the following situation:
function functionExists(functionName) {
if (typeof window[functionName] == 'function') console.log("It's a function");
}
What would be an equivalent function in nodejs for functionExists where there is no global window variable?
CONCRETE SITUATION:
My concrete situation uses webpack instead of nodejs, but basically the problem is the same. I could use window here, but it would be too complicated to implement everything cleanly, and it isn't advised by webpack to mitigate things out to the window global variable.
Basically, I have a PHP backend, which generates a html <form> adding some options to it via a data attribute. When the page is loaded, my javascript initializes this <form> and gives it a bunch of functionalities (like validation for example). Another thing javascript does with this form, is that it parses the data attribute of it, and instead of the normal page reload submit, it changes the form so it is being submited over an ajax request to the server.
When this submit happens, it is set up, that the button and the whole form gets disabled, until my Ajax script sends back a response. How this is done, is that I have a Project_Form class, which when it is initialized, attaches itself to the jQuery submit event, stops the basic submit event, and runs an inner function which sends an ajax request to an api method. The ajax request is set up, that when a response is received, the same instantiated class will receive this response, so I can continue working with it.
When the form receives the response, it must do something with it. In the most basic situation, it must show a success message to the user, but there are some more complex situation, where for example, it has to make a page redirect (for example a login form). Right now, it is set up, that as a default, it will show a message, but when I define this form in PHP, I have the option to "hijack" this default behaviour, and instead of it, send the ajax response to a custom function, which will resolve the situation specifically.
When I am rendering the form in PHP, I already know where the form should send a success response (to which javascript function), but I can only provide this information to javascript, via a string. So my Project_Form class, should fetch this string, and should try to fetch a function from it which it will use. This is where my problem is coming from.
Unless you specifically KNOW that this is a global function (which is almost never the case in nodejs), functions by default in nodejs are scoped to the module and there is NO way to look them up by string name like you did with the window object in the browser, just like there is no way to look up local variables by name inside a function in Javascript.
In general, don't pass functions by string name. Or, if you have to, then you need to create a lookup table that you can check the function name against.
I'd suggest you explain the real problem you're trying to solve here because passing the function by string name is not how you would generally want to do things.
There is a bit of a hack using eval() that can see if a string represents a function name that is in scope:
// Warning, you must know that the argument f (if it is a string) does not
// contain harmful Javascript code because it will be used with eval()
function isFunction(f) {
// if already a function reference
if (typeof f === "function") {
return true;
// see if string represents a function name somewhere in scope
} else if (typeof f === "string") {
try {
return eval(`typeof ${f} === "function"`);
} catch(e) {
return false;
}
} else {
return false;
}
}
Note: This tests to see if the function is in the scope of the isFunction() function. If you want to test if it's in your current scope, then you need to do the:
eval(`typeof ${f} === "function"`)
inline in your current scope so it runs in the scope you want to do the lookup from.
To ever consider using this, you will HAVE to know that the source of your string is safe and cannot contain harmful code. But, as I said earlier, it's better to design your program differently so you aren't referring to functions by their string name.
And, here's a runnable snippet that shows it in action (also works in a node.js module):
function test() {
console.log("in test");
}
function isFunction(f) {
// if already a function reference
if (typeof f === "function") {
return true;
// see if string represents a function name somewhere in scope
} else if (typeof f === "string") {
try {
return eval(`typeof ${f} === "function"`);
} catch(e) {
return false;
}
} else {
return false;
}
}
console.log(isFunction("test")); // true
console.log(isFunction(test)); // true
console.log(isFunction("notAFunction")); // false
More added after question edit
If you only have the function name as a string and the function that it points to is not a property of some known object, then the only way I know of to turn that string into a function reference is with eval().
You could directly execute it with eval() such as eval(functionName + "()") or you could get a reference to the function with eval("let fn = " + functionName) and then use the newly defined fn variable to call the function.
If you control the various functions that could be referenced (because they're your Javascript), then you can make all those functions be a property of a known object in your Javsacript:
const functionDispatcher = {
function1,
function2,
function3,
function4
}
Then, instead of using eval(), you can reference them off the functionDispatcher object like you would have referenced before with window (except this isn't a global) as in:
functionDispatcher[someFunctionName]();
This would be a preferred option over using eval() since there is less risk of insertion of random code via an unsafe string.
In node.js you can achieve this like:
function functionExists(functionName) {
if(functionName && typeof functionName === "function")
console.log("It is a function");
}
Hope this works for you.
I am new to nodejs. Using bluebird promises to get the response of an array of HTTP API calls, and storing derived results in an ElasticSearch.
Everything is working fine, except I am unable to access the variables within the 'then' function. Below is my code:
Promise.map(bucket_paths, function(path) {
this.path = path;
return getJson.getStoreJson(things,path.path);
}, {concurrency:1}).then(function(bucketStats){
bucketStats.map(function(bucketStat) {
var bucket_stats_json = {};
bucket_stats_json.timestamp = new Date();
bucket_stats_json.name = path.name ==> NOT WORKING
});
});
How can I access the path.name variable within the 'then' ? Error says 'path' is undefined.
The best way to do this is to package the data you need from one part of the promise chain into the resolved value that is sent onto the next part of the chain. In your case with Promise.map(), you're sending an array of data onto the .then() handler so the cleanest way to pass each path down to the next stage is to make it part of each array entry that Promise.map() is resolving. It appears you can just add it to the bucketStat data structure with an extra .then() as show below. When you get the data that corresponds to a path, you then add the path into that data structure so later on when you're walking through all the results, you have the .path property for each object.
You don't show any actual result here so I don't know what you're ultimately trying to end up with, but hopefully you can get the general idea from this.
Also, I switched to Promise.mapSeries() since that's a shortcut when you want concurrency set to 1.
Promise.mapSeries(bucket_paths, function(path) {
return getJson.getStoreJson(things,path.path).then(bucketStat => {
// add the path into this item's data so we can get to it later
bucketStat.path = path;
return bucketStat;
});
}).then(function(bucketStats){
return bucketStats.map(function(bucketStat) {
var bucket_stats_json = {};
bucket_stats_json.timestamp = new Date();
bucket_stats_json.name = bucketStat.path.name;
return bucket_status_json;
});
});
From a websocket I'm getting this data which I'm printing using console.log on a Linux console(using putty):
{"report":"IP Report:\n35.194.173.178:1"}
I want it to create a newline whereever "\n" is there in the string. How to achieve this?
What you're getting here is a JSON string. You need to parse it using JSON.parse() (inside a try/catch block because it can throw an exception on bad input - or you can use my tryjson module).
When you parse it you'll get an object whose report property is the string that you need to print.
Simplest example:
const obj = JSON.parse(yourData);
console.log(obj.report);
but make sure to add error handling:
try {
const obj = JSON.parse(yourData);
console.log(obj.report);
} catch (err) {
// handle the error
}
In my node application i'm using redis DB to store the data.While getting the stored value using key i'm not getting the expected output.
var redis=require('redis');
var client = redis.createClient();
var pageContent={a: "a", b: "b", c: "c"};
//client.set('A',pageContent);//here i'm setting the value
client.get('A',function(err,res){
if(!err){
Object.keys(res).forEach(function(k){
console.log('key is '+k + ' value is '+res[k]);
});
}
else{
console.log('error');
}
});
Above code is not giving the stored value.While looping the result i'm getting the below error
TypeError: Object.keys called on non-object
So i have tried res.toString(); but i'm not getting the stored value instaed of that i'm getting only [object object];
The issue is that you are trying to save an object with SET. In redis, SET and GET only work with strings, so the reason you get [object Object] back is that's the string which was saved in redis -- the string representation of your object.
You can either serialize your objects as e.g. JSON, using JSON.stringify when saving, and JSON.parse when reading, or you can save your objects as redis hashes, using HMSET when saving, and HGETALL (or HGET / HMGET) when reading.
Edit: Note, though, that if you decide to use redis hashes, you cannot have "nested" objects -- i.e., you cannot store an object where one of the properties is an array or another object. That is,
{
a: 1,
b: 2
}
is okay, while
{
a: {
b: 2
}
}
is not. If you have such objects, you need another model (JSON with SET/GET works perfectly well in this case).