'javascript] Object's value update strangely

The value of the object is updated very strangely. the current overall system structure is as follows.

  1. There is a server that collects the status of each system.
  2. Send the collected data from the server to the web server through websocket
  3. When the web server receives the websocket, the callback function is called.
  4. In the callback function, the object is updated with the received data.

The problem occurs when updating objects.

Here is the code for that part.

var systemDatas = {};
...


fn_callback = function(data){
    fn_set_metric(data);
    ...
};
...


function fn_set_metric(data){
    Object.entries(data).forEach(([apps, appArr]) => {
        for(let i = 0; i < appArr.length; i++){
            var app = {};
            if(appArr[i].name === "GW"){
                if(systemDatas.hasOwnProperty("GW")){
                    var gwDatas = systemDatas["GW"];
                    Object.keys(gwDatas).map(function(key){
                        try {       
                            var keyIdx = 0;
                            for(let j = 0; j < (appArr[i].nodes).length ; j++){
                                if(appArr[i].nodes[j].name === key){
                                    keyIdx = j;
                                    break;
                                }
                            }
                            if(appArr[i].nodes[keyIdx].health === "on"){
                                gwDatas[key].process.cpuSystem = appArr[i].nodes[keyIdx].metrics[0].measurements[0].value;
                                gwDatas[key].process.cpuProcess = appArr[i].nodes[keyIdx].metrics[1].measurements[0].value;
                                gwDatas[key].memory.memUsed = appArr[i].nodes[keyIdx].metrics[2].measurements[0].value;
                                gwDatas[key].memory.heapUsed = appArr[i].nodes[keyIdx].metrics[4].measurements[0].value;
                                gwDatas[key].thread.threadDeamon = appArr[i].nodes[keyIdx].metrics[6].measurements[0].value;
                                gwDatas[key].thread.threadLive = appArr[i].nodes[keyIdx].metrics[7].measurements[0].value;
                                gwDatas[key].memory.memMax = appArr[i].nodes[keyIdx].metrics[3].measurements[0].value;
                                gwDatas[key].memory.heapMax = appArr[i].nodes[keyIdx].metrics[5].measurements[0].value;
                                gwDatas[key].thread.threadPeak = appArr[i].nodes[keyIdx].metrics[8].measurements[0].value;
                                gwDatas[key].process.uptime = appArr[i].nodes[keyIdx].metrics[9].measurements[0].value;
                                gwDatas[key].process.cpuCount = appArr[i].nodes[keyIdx].metrics[10].measurements[0].value;
                                
                                console.log(key);
                                console.log(systemDatas["GW"][key].process.uptime);
                                console.log(systemDatas["GW"][key].process);
                                console.log(systemDatas["GW"][key]);
                                console.log(systemDatas["GW"]);
                                
                            }
                        }
                        catch(e) {
                           console.error(e);
                        }
                    });
                }
                ...
}



and the result of executing the function. console.log

As you can see in the area marked in yellow in the result image. depending on the scope of the object, the value is different.

my expectation is after systemDatas["GW"]["GW_1"] is updated, systemDatas["GW"]["GW_2"] is updated. sequentially. but it's behaving in an incomprehensible way

except the callback function there is no part to update systemDatas.

Can you explain why it works this way?



Solution 1:[1]

Your code complexity (nesting) is to high - It is not helping you solve the problem.

Fixes

  1. Break the function up into 2-3 separate functions const parseMetricsData, parseGWData; // etc..
  2. Look over latest added Array methods, some of the new ones like [].find will make the code easier to read (MDN Array Docs).

Other tips after code example.

Example:

const systemDatas = {};

// ...


const fn_callback = function (data) {
  fn_set_metric(data);
  // ...
};

// ...

const parseGWData = (app, gwDatas) => {
  for (const key of gwDatas.keys()) {
    const gwData = gwData || {},
      foundNode = !app.nodes ? null : app.nodes.find(n => n.name === key);

    if (!foundNode || foundNode.health !== 'on') continue;

    gwData.process.cpuSystem = foundNode.metrics[0].measurements[0].value;
    gwData.process.cpuProcess = foundNode.metrics[1].measurements[0].value;
    gwData.process.uptime = foundNode.metrics[9].measurements[0].value;
    gwData.process.cpuCount = foundNode.metrics[10].measurements[0].value;
    gwData.memory.memUsed = foundNode.metrics[2].measurements[0].value;
    gwData.memory.heapUsed = foundNode.metrics[4].measurements[0].value;
    gwData.memory.memMax = foundNode.metrics[3].measurements[0].value;
    gwData.memory.heapMax = foundNode.metrics[5].measurements[0].value;
    gwData.thread.threadDeamon = foundNode.metrics[6].measurements[0].value;
    gwData.thread.threadLive = foundNode.metrics[7].measurements[0].value;
    gwData.thread.threadPeak = foundNode.metrics[8].measurements[0].value;

    console.log(key);
    console.table(systemDatas.GW[key])
  }
};

function fn_set_metric(data) {
  for (const [apps, appArr] of Object.entries(data)) {
    for (const app of appArr) {
      if (app.name !== 'GW' ||
        !Object.prototype.hasOwnProperty.call(systemDatas, 'GW')) continue;
      parseGWData(systemDatas.GW);
    }
  }
}

Other code tips:

  • Put long property chains into variables, either via built-ins (app.nodes.find(app => app.name === key)) or directly.
  • Use built-ins (Array.prototype.find, for of loops etc. (use whatever your platform/platform version supports (see MDN Array, etc., for more).
  • Use negative if checks (instead of nesting main part of code in if statements you can check the opposite condition to avoid creating deeply nested code).
  • ~~Consider not mutating static structures until loops/manipulations are complete; E.g., perform manipulations on pure, new, objects and then merge results into static structure(s) - will help you pinpoint issues~~ Consider that appArr may have duplicate app entries which may be overriding each others' values.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1