Integer limit and extract from payload

Hi i am new to nodered and json programming,

i am trying to get the total numder of API call , i encounter i problem and error in my code:
1)

var total = msg.payload.data.count;

for (var i = 0; i< total; i++){
    data.push({"x":msg.payload.data.datastreams[1].datapoints[i].at, "y":msg.payload.data.datastreams[1].datapoints[i].value});
}

the above is error because total is still in Json?
how can i make use ff that ?

  1. i have also try using switch node
    to switch msg.payload to global.number(payload)

but it will come error also

  1. how can i handle big/large integer number if its a long value?
    thanks

Jeff

Hi @apex

it's quite hard to say what is happening without more details. What error are you actually hitting? Can you pass your message to a Debug node so we can see exactly what you are working with?

Do you mean you want to set msg.payload to the value of a global context value? If so, you should use the Change node to do that, not the Switch node. I'm also not sure what you intend with global.number(payload). Again, without information on what actual error you are getting it is hard to know what you are doing.

How big is big? In JavaScript, the largest number you can represent is 9007199254740991. Otherwise you have to use the BigInt type - BigInt - JavaScript | MDN

hi thanks for reply.
I m using mobile so i only can elaborate with words
i am using an webapi so i am getting the data and plot it into chart .
And one of the stream "datapoint" from the Api is the "total Api call" .
and i wanna make use of it for some function like
for loop
and so what i have tryed is
var number = msg.payload.datapoint.count
what i try is stored the number of api call to an integer variable "number"
and so i can make use of it like
(for i=0, i<number , i++)
{ do sth for array[i]}
thanks

We don't know what the error is though and without that, it is very hard to give advice. It could be that msg.payload.data.count is a property that doesn't exist? It could also be that you meant to write msg.payload.data.length (with msg.payload.data being an array) though from your other code, that doesn't look likely? It could also be that msg.payload.data.count exists but as a string and not as a number.

You also have another issue in that you haven't declared data as an array variable. So you will certainly get an error there.

We just don't have enough information.

thanks ~

this is the node to debug one of the "data" in my nodered from API

[{"id":"980fe654.f77208","type":"debug","z":"25c3e47b.ae7f9c","name":"number of log","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":1090,"y":560,"wires":[]},{"id":"30ceee4c.224562","type":"function","z":"25c3e47b.ae7f9c","name":"log count","func":"msg.payload = msg.payload.data.count;\nreturn msg;","outputs":1,"noerr":0,"x":840,"y":560,"wires":[["980fe654.f77208","88b5bfb3.54283"]]}]

//=================
and it shows the debug result here:
3/27/2020, 12:40:54 PMnode: number of log
msg.payload : number
600
//===============
and so i wanna make use of the 600 to make a for loop
and my for loop is here

var total = msg.payload.data.count;
//var total = context.get('count');
//var total = parseInt(msg.payload.data.count,10);
//var total = Number(msg.payload.data.count);
//abcd = total.toFixed(1);
let data =[];
//for (let prop in msg.payload) {
//    data.push({"x":msg.payload.data.datastreams[1].datapoints[prop].value, "y":msg.payload[prop].at});
//}

for (var i = 0; i< total; i++){
    data.push({"x":msg.payload.data.datastreams[1].datapoints[i].at, "y":msg.payload.data.datastreams[1].datapoints[i].value});
}
//payload.data.datastreams[1].datapoints[0].value

msg.data = data;
return msg;

and the error message
"TypeError: Cannot read property 'at' of undefined"

thanksif anyone can help

Jeff

You have tried to access a non-existent property here. Something in that chain doesn't actually exist. You need to dump the input msg to debug immediately before this function node. You can then use the little icons in the debug panel to copy an example path.

but when i modified the for loop
(for var i =0, i<10, i++)
everything works ...
so i am still confuesd

Try

var total = msg.payload.data.datastreams[1].datapoints.length

Possibly count (whatever that is) is not set correctly.
If you add at the start the lines

node.warn("count is " + msg.payload.data.count)`
node.warn("length is " + msg.payload.data.datastreams[1].datapoints.length)

you will get a message in the debug pane telling you what the values are.

[quote="apex, post:5, topic:23662"]

[{"id":"980fe654.f77208","type":"debug","z":"25c3e47b.ae7f9c","name":"number of log","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":1090,"y":560,"wires":[]},{"id":"30ceee4c.224562","type":"function","z":"25c3e47b.ae7f9c","name":"log count","func":"msg.payload = msg.payload.data.count;\nreturn msg;","outputs":1,"noerr":0,"x":840,"y":560,"wires":[["980fe654.f77208","88b5bfb3.54283"]]}]

//=================
[/quote] thanks
i am in mobile now so formatting is hard

[{"id":"980fe654.f77208","type":"debug","z":"25c3e47b.ae7f9c","name":"number of log","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":1090,"y":560,"wires":[]},{"id":"30ceee4c.224562","type":"function","z":"25c3e47b.ae7f9c","name":"log count","func":"msg.payload = msg.payload.data.count;\nreturn msg;","outputs":1,"noerr":0,"x":840,"y":560,"wires":[["980fe654.f77208","88b5bfb3.54283"]]}]

//=================

actually the msg.payload.data.count; is an number of total of api call
and in this example is 600
i can get the result from the

msg = msg.payload.data.count
return msg

and link it to debug message node the result is 600

and so i wanna make use of it like
for(int i =0, i < msg.payload.data.count, i++)
{
show msg.payload.xxx[i] sth or do sth
}
thanks

In your original code you have
msg.payload.data.datastreams[1].datapoints[i]
which means take the first element of datastreams and then the ith element of datapoints, which means that you expect datapoints to be 600 elements long, within the first element of datastreams. Is that correct?
I think we need to understand what you have actually got in msg.payload. Feed the incoming message into a debug node and show us what you get.

ok .here is the display of the debug message

3/30/2020, 1:00:32 PMnode: test3
msg.payload : Object
object
errno: 0
data: object
cursor: "289445_576330540_1578380250555"
count: 10
datastreams: array[2]
0: object
datapoints: array[5]
0: object
at: "2020-01-07 14:43:27.490"
value: "abcdefghijklmnopqrstuvwxyz0123"
1: object
at: "2020-01-07 14:46:42.845"
value: "abcdefghijklmnopqrstuvwxyz0123"
2: object
at: "2020-01-07 14:50:00.451"
value: "abcdefghijklmnopqrstuvwxyz0123"
3: object
4: object
id: "3311_0_5706"
1: object
datapoints: array[5]
id: "3311_0_5851"
error: "succ"

thanks

So there you have count is 10 but there are only 5 items in array[1].datapoints. So in your loop when i gets to 5 and you use
msg.payload.data.datastreams[1].datapoints[i].at
then you are off the end of the datapoints array.

1 Like

thanks!!!!!

It is almost always safer to use Array.length for looping arrays, that guarantees you will not go off the end.

can you show me more ?

var numDataPoints = msg.payload.data.datastreams[1].datapoints.length
for (var i = 0; i< numDataPoints; i++){ 
  data.push({"x":msg.payload.data.datastreams[1].datapoints[i].at, "y":msg.payload.data.datastreams[1].datapoints[i].value}); 
}

thanks will have a try in coming day !

Better still, use JavaScripts forEach() function.

While a for loop might be marginally faster when done right, there is so little in it, the improved logic and simplicity of forEach is often better.

msg.payload.data.datastreams[1].datapoints.forEach( datapoint => {
  data.push( { "x": datapoint.at, "y": datapoint.value } ); 
} )

I am not sure about using forEach as a beginner. The syntax is not as obvious as a simple loop.

Each to their own I expect as usual :slight_smile:

Personally, I find forEach a lot easier to get my head around and certainly the code inside the loop tends to be quite a bit simpler. And you don't have to worry about counts and whether you put the var/let in or remember to use ; not ,.

Using the ES6 style function definition as I have done here does take a little getting used to. That's why I tend to be careful in using extra spacing. You can, of course use the traditional format if you prefer:

somearray.forEach( function(datapoint) {
    ....
})

And you have the optional other 2 paramters as well if you need them:

somearray.forEach( (datapoint, i, origArray) => {
    ...
})