Pass array values as parameter to function and create json data - javascript

I have a scenario where I am passing an array of objects to a function in nodejs, but the same is failing with undefined error.
Here is what I have tried :
var object = issues.issues //json data
var outarr=[];
for(var key in object){
outarr.push(object[key].key)
}
console.log(outarr) // array is formed like this : ['a','b','c','d','e']
for(var i =0; i<outarr.length;i++){
jira.findIssue(outarr[i]) //here I am trying to pass the array objects into the loop one by one
.then(function(issue) {
var issue_number = issue.key
var ape = issue.fields.customfield_11442[0].value
var description = issue.fields.summary
var ice = issue.fields.customfield_15890[0].value
var vice = issue.fields.customfield_15891.value
var sor = issue.fields.labels
if (sor.indexOf("testcng") > -1) {
var val = 'yes'
} else {
var val = 'yes'
}
var obj = {};
obj['ape_n'] = ape;
obj['description_n'] = description;
obj['ice_n'] = ice;
obj['vice_n'] = vice;
obj['sor_n'] = val;
var out = {}
var key = item;
out[key] = [];
out[key].push(obj);
console.log(out)
} })
.catch(function(err) {
console.error(err);
});
});
What I am trying to achieve : I want to pass the array values as a parameter which is required by jira.findissue(bassically passing the issue number) one by one and which should again fetch the values and give a combine json output.
How can I pass this array values one by one in this function and also run jira.findissue in loop.
Any help will be great !! :-)

I have taken a look at the code in your question.
To be honest the code you wrote is messy and contains some simple syntax errors.
A good tip is to use a linter to avoid those mistakes.
More info about linters here: https://www.codereadability.com/what-are-javascript-linters/
To output all results in one array you have to define the array outside the scope of the loop.
I cleaned the code a bit up and use some es6 features. I don't know the context of the code but this is what I can make off it:
//map every value the key to outarr
let outarr = issues.issues.map( elm => elm.key);
//Output defined outside the scope of the loop
let output = [];
//looping outarr
outarr.forEach( el => {
jira.findIssue(el).then(issue => {
//creating the issue object
let obj = {
ape_n: issue.fields.customfield_11442[0].value,
description_n: issue.fields.summary,
ice_n: issue.fields.customfield_15890[0].value,
vice_n: issue.fields.customfield_15891.value,
sor_n: issue.fields.labels.indexOf("testcng") > -1 ? "yes" : "yes",
};
//pushing to the output
output[issue.key] = obj;
}).catch(err => {
console.log(err);
});
});
//ouputing the output
console.log(output);
Some more info about es6 features: https://webapplog.com/es6/

Related

javascript] Object's value update strangely

The value of the object is updated very strangely.
the current overall system structure is as follows.
There is a server that collects the status of each system.
Send the collected data from the server to the web server through websocket
When the web server receives the websocket, the callback function is called.
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?
Your code complexity (nesting) is to high - It is not helping you solve the problem.
Fixes
Break the function up into 2-3 separate functions const parseMetricsData, parseGWData; // etc..
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.

how do I check if a value is in a JSON return or not?

I'm writing a test in postman where I want to check if a JSON return contains the Label called 'RegressieMapTest'. This is my script:
pm.test("Is the folder created correctly?", function(){
var jsonData = pm.response.json();
var objString = JSON.stringify(jsonData);
var obj = JSON.parse(objString);
for (var i = 0; i < obj.Corsa.Data.length; i++){
if (obj.Corsa.Data[i].Label == "RegressieMapTest"){
console.log(obj.Corsa.Data[i].Label);
pm.expect(obj.Corsa.Data.Label).to.eql("RegressieMapTest");
}
}
pm.expect.fail();
})
But it doesn't quite work, every time I run this script it seems like it automatically jumps to pm.expect.fail() which is weird because 'RegressieMapTest' is inside the JSON return. Postman returns the following message:
Is the folder created correctly? | AssertionError: expect.fail()
pm.respose.json() is equalent to JSON.parse you don't have to do it again
also you can use array.find method instead of looping through it
pm.test("Is the folder created correctly?", function () {
var jsonData = pm.response.json();
pm.expect(obj.Corsa.Data.find(elem => elem.Label === "RegressieMapTest")).to.be.not.undefined
}
if array has any element with label RegressieMapTest then it will return that data elese returns undefined, so we are validating that it will not return undefined. Meaning it has the value
Your pm.expect.fail(); always runs. You want it to run only when you don't find the field. So just add a flag in your check block.
pm.test("Is the folder created correctly?", function(){
var jsonData = pm.response.json();
var objString = JSON.stringify(jsonData);
var obj = JSON.parse(objString);
var isFound = false;
for (var i = 0; i < obj.Corsa.Data.length; i++){
if (obj.Corsa.Data[i].Label == "RegressieMapTest"){
console.log(obj.Corsa.Data[i].Label);
pm.expect(obj.Corsa.Data.Label).to.eql("RegressieMapTest");
isFound = true;
}
}
if (!isFound) {
pm.expect.fail();
}
})

firebase - javascript object returning undefined

I have a firebase set up. here is the structure:
I am having trouble getting the 'newNroomID' value (that is a6QVH, a7LTN etc..).
this value will be use to compare with the other variable value.
I know that in javascript, to access the value of the object it can be done like this:
var card = { king : 'spade', jack: 'diamond', queen: 'heart' }
card.jack = 'diamond'
but it seems different story when it comes with the firebase or surely enough i am missing something. Here is my code.
var pokerRoomsJoin = firebase.database().ref(); // this is how i set it up this block of code is for reading the data only
pokerRoomsJoin.on('value', function(data){
var rID = data.val();
var keys = Object.keys(rID);
var callSet = false;
for (var i = 0 ; i < keys.length; i++) {
var indexOfKeys = keys[i];
var roomMatching = rID[indexOfKeys];
var matchID = roomMatching.newNroomID; // this does not work alwaus give me undefined
console.log('this return :' + matchID + ' WHY!')
console.log(roomMatching)
if(matchID == 'ffe12'){ // 'ffe12' is actually a dynamic value from a paramiter
callSet = true;
}
}
})
and here is the result of the console log:
strangely i am able to access it like this
var matchID = roomMatching.newNroomID // it return a6QVH and a7LTN one at a time inside the loop
only if i set up the ref to :
var pokerRoomsJoin = firebase.database().ref('room-' + roomId);
I've tried searching but seems different from the structure i have . am I having bad data structure? Save me from this misery , thanks in advance!
Let us see the code inside for loop line by line,
1. var indexOfKeys = keys[i];
now indexOfKeys will hold the key room-id
2. var roomMatching = rID[indexOfKeys];
here roomMatching will hold the object
{ 'firebasePushId': { newDealerName: 'b',
...,
}
}
Now
3. var matchID = roomMatching.newNroomID;
This of-course will be undefined because roomMatching has only one
property , firebasePushId.
To access newNroomID , you have to do something like this,
matchID = roomMatching.firebasePushKey.newNroomID .
One way to get firebasePushKeys will be using Object.keys(roomMatching).

How to convert values of an array into recursive field names of another variable in Javascript

I need to convert values from one Array variable into fields of another variable in Javascript.
My variable is
field = ["entries", "body"]
and it needs to become something like
req.body.entries.body
I tried doing something like
field.forEach(function(prop){
req.body[prop] = "...";
}
but that works only on req.body.entries and req.body.body. And I need it to go all the way to req.body.entries.body
I'm doing this to get the data from a form in a document field (named entries[body]), do some cleaning up on that data, and then pass it back to node.js as if it was the request that was originally made.
UPDATE
All I need to do is to basically
exports.sanitize = function(field){
// field = ["entry","body"];
return function(req, res, next){
val = getField(req, field); // val = "Some string with data"
val = some_process(val); // some_process is a function that cleans up the string
req.body.entry.body = val; // HOW TO TAKE entry.body from the field array???
next();
}
};
As you can see, all I want is to NOT hard code entry.body but take it from field array values that passes the name of the field for processing.
If you can think of a more elegant solution to do this, please, let me know.
Thanks!
This works:
var fields = [ "field1", "field2", "field3", "field4" ];
var obj = req.body;
fields.forEach(function(prop) {
obj[prop] = {};
obj = obj[prop];
});
You want
var obj = req.body;
for (var i=0; i<fields.length-1; i++)
obj = obj[fields[i]];
var prop = fields[i];
obj[prop] = cleanUp(obj[prop]);
This will work only if req.body.entries.body is already defined:
field = ["entries","body"];
var toeval="req.body";
field.forEach(function(prop){
toeval+="."+prop;
});
toeval+="=\"...\"";
eval(toeval);
I was able to accomplish this using recursion. Hope this helps!
var foo = {
bar: {}
};
var fields = ['foobar', 'barfoo'];
function setVar (currentVar, arr, counter) {
if (arr[counter] === undefined) {
return;
}
currentVar[arr[counter]] = {};
setVar(currentVar[arr[counter]], arr, counter + 1);
}
setVar(foo.bar, fields, 0);

return from JS function

basic JS question, please go easy on me I'm a newb :)
I pass 2 variables to the findRelatedRecords function which queries other related tables and assembles an Array of Objects, called data. Since findRelatedRecords has so many inner functions, I'm having a hard time getting the data Array out of the function.
As it currently is, I call showWin inside findRelatedRecords, but I'd like to change it so that I can get data Array directly out of findRelatedRecords, and not jump to showWin
function findRelatedRecords(features,evtObj){
//first relationship query to find related branches
var selFeat = features
var featObjId = selFeat[0].attributes.OBJECTID_1
var relatedBranch = new esri.tasks.RelationshipQuery();
relatedBranch.outFields = ["*"];
relatedBranch.relationshipId = 1; //fac -to- Branch
relatedBranch.objectIds = [featObjId];
facSel.queryRelatedFeatures(relatedBranch, function(relatedBranches) {
var branchFound = false;
if(relatedBranches.hasOwnProperty(featObjId) == true){
branchFound = true;
var branchSet = relatedBranches[featObjId]
var cmdBranch = dojo.map(branchSet.features, function(feature){
return feature.attributes;
})
}
//regardless of whether a branch is found or not, we have to run the cmdMain relationship query
//the parent is still fac, no advantage of the parent being branch since cmcMain query has to be run regardless
//fac - branch - cmdMain - cmdSub <--sometimes
//fac - cmdMain - cmdSub <-- sometimes
//second relationship query to find related cmdMains
var relatedQuery = new esri.tasks.RelationshipQuery();
relatedQuery.outFields = ["*"];
relatedQuery.relationshipId = 0; //fac -to- cmdMain
relatedQuery.objectIds = [featObjId];
//rather then listen for "OnSelectionComplete" we are using the queryRelatedFeatures callback function
facSel.queryRelatedFeatures(relatedQuery, function(relatedRecords) {
var data = []
//if any cmdMain records were found, relatedRecords object will have a property = to the OBJECTID of the clicked feature
//i.e. if cmdMain records are found, true will be returned; and continue with finding cmdSub records
if(relatedRecords.hasOwnProperty(featObjId) == true){
var fset = relatedRecords[featObjId]
var cmdMain = dojo.map(fset.features, function(feature) {
return feature.attributes;
})
//we need to fill an array with the objectids of the returned cmdMain records
//the length of this list == total number of mainCmd records returned for the clicked facility
objs = []
for (var k in cmdMain){
var o = cmdMain[k];
objs.push(o.OBJECTID)
}
//third relationship query to find records related to cmdMain (cmdSub)
var subQuery = new esri.tasks.RelationshipQuery();
subQuery.outFields = ["*"];
subQuery.relationshipId = 2;
subQuery.objectIds = [objs]
subTbl.queryRelatedFeatures(subQuery, function (subRecords){
//subRecords is an object where each property is the objectid of a cmdMain record
//if a cmdRecord objectid is present in subRecords property, cmdMain has sub records
//we no longer need these objectids, so we'll remove them and put the array into cmdsub
var cmdSub = []
for (id in subRecords){
dojo.forEach(subRecords[id].features, function(rec){
cmdSub.push(rec.attributes)
})
}
var j = cmdSub.length;
var p;
var sub_key;
var obj;
if (branchFound == true){
var p1 = "branch";
obj1 = {};
obj1[p1] = [cmdBranch[0].Branches]
data.push(obj1)
}
for (var i=0, iLen = cmdMain.length; i<iLen; i++) {
p = cmdMain[i].ASGMT_Name
obj = {};
obj[p] = [];
sub_key = cmdMain[i].sub_key;
for (var j=0, jLen=cmdSub.length; j<jLen; j++) {
if (cmdSub[j].sub_key == sub_key) {
obj[p].push(cmdSub[j].Long_Name);
}
}
data.push(obj);
}
showWin(data,evtObj) <---this would go away
})
}
//no returned cmdRecords; cmdData not available
else{
p = "No Data Available"
obj = {}
obj[p] = []
data.push(obj)
}
showWin(data,evtObj) <--this would go away
})
})
}
I'd like to have access to data array simply by calling
function findRelatedRecords(feature,evt){
//code pasted above
}
function newfunct(){
var newData = findRelatedRecords(feature,evt)
console.log(newData)
}
is this possible?
thanks!
Edit
Little more explanation.....
I'm connecting an Object event Listener to a Function like so:
function b (input){
dojo.connect(obj, "onQueryRelatedFeaturesComplete", getData);
obj.queryRelatedFeatures(input);
console.log(arr) //<----this doesn't work
}
function getData(relatedFeatData){
var arr = [];
//populate arr
return arr;
}
So when obj.QueryRelatedFeatures() is complete, getData fires; this part works fine, but how to I access arr from function b ?
Post Edit Update:
Due to the way that this event is being hooked up you can't simple return data from it. Returning will just let Dojo call to the next method that is hooked up to onSelectionComplete.
When init runs it is long before findRelatedRecords will ever be executed/fired by the onSelectionComplete event of the well, which is why you were seeing undefined/null values. The only way to work with this sort of system is to either 1) call off to a method like you're already doing or 2) fire off a custom event/message (technically it's still just calling off to a method).
If you want to make this method easier to work with you should refactor/extract snippets of it to make it a smaller function but contained in many functions. Also, changing it to have only one exit point at the end of the findRelatedRecords method will help. The function defined inside of subTbl.queryRelatedFeatures() would be a great place to start.
Sorry, you're kind of limited by what Dojo gives you in this case.
Pre Edit Answer:
Just return your data out of it. Everywhere where there is a showWin call just use this return.
return {
data: data,
evtObj: evtObj
}
Then your newfunct would look like this.
function newfunct(){
var newData = findRelatedRecords(feature,evt);
console.log(newData);
console.log(newData.data);
console.log(newData.evtObj);
}
If you only need that "data" object, then change your return to just return data;.
Also, start using semicolons to terminate statements.

Categories

Resources