Node.js array instantiation - javascript

So, I have been trying for a while now and no luck. Currently I have an associative array as based on PSN profile data:
var PROFILE = {};
PROFILE.profileData = {};
PROFILE.titles = {};
and is used like this further down in the code:
PROFILE.profileData.onlineId = profileData.onlineId;
PROFILE.profileData.region = profileData.region;
PROFILE.titles[title.npCommunicationId] = title; //For looped, can be many
PROFILE.titles[title.npCommunicationId].trophies = {};
PROFILE.titles[title.npCommunicationId].trophies = trophyData.trophies; //any where from 10 - 50+ of these, for looped
Problem is, if I want to have multiple profiles, this doesn't work as it just inserts them in the same profile. I need 'PROFILE' to be an array that has all the above elements at each index.
PROFILEarray[n].profileData = {};
PROFILEarray[n].profileData.onlineId = profileData.onlineId;
PROFILEarray[n].profileData.region = profileData.region;
Something like this is what I need^
But for the above I get this error
Cannot read property 'profileData' of undefined
Once this is complete, it's saved into a file in JSON format to then be used by PHP code I've written to insert into a db.
This is a small snippet of the json output: http://textuploader.com/5zpbk (had to cut, too bit to upload)

you must define PROFILEarray[n] as object. JavaScript objects are containers for named values. You can not set value of undefined
PROFILEarray[n] is undefined in this case. Initialize it as {}(object)
Try this:
var PROFILEarray = [];
for (var n = 0; n < 5; n++) {
PROFILEarray[n] = {};
PROFILEarray[n].profileData = {};
PROFILEarray[n].profileData.onlineId = n;
PROFILEarray[n].profileData.region = 'Region' + n;
}
alert(JSON.stringify(PROFILEarray));

Related

Why is this JavaScript looping twice in Zapier?

Here is a video that shows what I'm struggling with.
Here is a high level description of the process, followed by the actual JavaScript code I've written.
PROCESS
I built 2 Zaps that each run like this:
STEP 1 - Trigger (Cognito Form, which has repeating sections)
STEP 2 - JavaScript Code (which creates an Array of the form fields for ONE of the repeating sections, and separates them into individual strings using .split)
STEP 3 - Action (creates a ZOHO CRM Task for each string)
The first Zap runs on one of the sections of the form (Visits with Sales), and the second zap runs on a different section of the form (Visits without Sales). Each of these Zaps works fine on their own so I know the code is good, but I want to combine the two Zaps into one by combining the code.
I tried to combine by making five steps:
Trigger - Code1 - Zoho1 - Code2 - Zoho2
but the Zoho2 Tasks were each repeated
I then tried to re-order the five steps:
Trigger - Code1 - Code2 - Zoho1 - Zoho2
but now Zoho1 Tasks AND Zoho2 tasks were duplicated.
Finally I tried to combine ALL the JavaScript code into one:
Tigger - CombinedCode1+2 - Zoho 1 - Zoho2
but only the strings from Arrays in "Code2" are available to me when I go to map them in Zoho1.
CODE:
if (inputData.stringVSAccount == null) {
var listVSAccountArray = [];
var listVSUnitsArray = [];
var listVSPriceArray = [];
var listVSNotesArray = [];
var listVSVisitCallArray = [];
} else {
var listVSAccountArray = inputData.stringVSAccount.split(",");
var listVSUnitsArray = inputData.stringVSUnits.split(",");
var listVSPriceArray = inputData.stringVSPrice.split(",");
var listVSNotesArray = inputData.stringVSNotes.split(",");
var listVSVisitCallArray = inputData.stringVSVisitCall.split(",");
}
var output = [];
var arrayNos = listVSAccountArray.length;
var i = 0;
do {
var thisItemVSAccount = new String(listVSAccountArray[i]);
var thisItemVSUnits = new String(listVSUnitsArray[i]);
var thisItemVSPrice = new String(listVSPriceArray[i]);
var thisItemVSNotes = new String(listVSNotesArray[i]);
var thisItemVSVisitCall = new String(listVSVisitCallArray[i]);
var thisItemObj = {};
thisItemObj.itemVSAccount = thisItemVSAccount;
thisItemObj.itemVSUnits = thisItemVSUnits;
thisItemObj.itemVSPrice = thisItemVSPrice;
thisItemObj.itemVSNotes = thisItemVSNotes;
thisItemObj.itemVSVisitCall = thisItemVSVisitCall;
output.push({ thisItemObj });
i++;
} while (i < arrayNos);
//This is where the second zaps code is pasted in the combined version
if (inputData.stringOVAccount == null) {
var listOVAccountArray = [];
var listOVNotesArray = [];
var listOVVisitCallArray = [];
} else {
var listOVAccountArray = inputData.stringOVAccount.split(",");
var listOVNotesArray = inputData.stringOVNotes.split(",");
var listOVVisitCallArray = inputData.stringOVVisitCall.split(",");
}
var output = [];
var arrayNos = listOVAccountArray.length;
var i = 0;
do {
var thisItemOVAccount = new String(listOVAccountArray[i]);
var thisItemOVNotes = new String(listOVNotesArray[i]);
var thisItemOVVisitCall = new String(listOVVisitCallArray[i]);
var thisItemObj = {};
thisItemObj.itemOVAccount = thisItemOVAccount;
thisItemObj.itemOVNotes = thisItemOVNotes;
thisItemObj.itemOVVisitCall = thisItemOVVisitCall;
output.push({ thisItemObj });
i++;
} while (i < arrayNos);
I just started learning JavaScript this week, and sense that I am missing something obvious, perhaps a set of brackets. Thanks for any assistance
David here, from the Zapier Platform team. You're running into a confusing and largely undocumented feature where items after a code step run for each item returned. This is usually desired behavior - when you return 3 submissions you want to create 3 records.
In your case, it's also running subsequent unrelated actions multiple times, which sounds like it's undesired. In that case, it might be easier to have 2 zaps. Or, if "Zoho2" only ever happens once, put it first and let the branch happen downstream.
Separately, I've got some unsolicited javascript advice (since you mentioned you're a beginner). Check out Array.forEach (docs), which will let you iterate through arrays without having to manage as many variables (your own i every time). Also, try to use let and const over var when possible - it keeps your variables scoped as small as possible so you don't accidentally leak values into other areas.
​Let me know if you've got any other questions!
Just a note - you are declaring the same array variable output in both segments of your code block - the second declaration will be ignored.
Use the .forEach() method to iterate over your arrays, it will significantly cleanup you code. You also don't need to painstakingly construct the objects to be pushed into the output arrays.
This may not fix your issue but the code is far easier on the eye.
var listVSAccountArray = [],
listVSUnitsArray = [],
listVSPriceArray = [],
listVSNotesArray = [],
listVSVisitCallArray = [],
output = [];
if (typeof inputData.stringVSAccount === 'string') {
listVSAccountArray = inputData.stringVSAccount.split(',');
listVSUnitsArray = inputData.stringVSUnits.split(',');
listVSPriceArray = inputData.stringVSPrice.split(',');
listVSNotesArray = inputData.stringVSNotes.split(',');
listVSVisitCallArray = inputData.stringVSVisitCall.split(',');
}
// iterate over the array using forEach()
listVSAccountArray.forEach(function(elem, index){
// elem is listVSAccountArray[index]
output.push({
itemVSAccount: elem,
itemVSUnits: listVSUnitsArray[index],
itemVSPrice: listVSPriceArray[index],
itemVSNotes: listVSNotesArray[index],
itemVSVisitCall: listVSVisitCallArray[index]
})
})
//This is where the second zaps code is pasted in the combined version
var listOVAccountArray = [],
listOVNotesArray = [],
listOVVisitCallArray = [],
output_two = []; // changed the name of the second output array
if (typeof inputData.stringOVAccount === 'string') {
listOVAccountArray = inputData.stringOVAccount.split(',');
listOVNotesArray = inputData.stringOVNotes.split(',');
listOVVisitCallArray = inputData.stringOVVisitCall.split(',');
}
// iterate over the array using forEach()
listOVAccountArray.forEach(function(elem, index){
// elem is listOVAccountArray[index]
output_two.push({
itemOVAccount: elem,
itemOVNotes: listOVNotesArray[index],
itemOVVisitCall: listOVVisitCallArray[index]
});
});

Putting an object into an array in JavaScript

I'm currently working with an MVC JS framework and I want to be able to get a list of objects that I can take a random entry out of on a loop. So far I've managed to create a function that finds a random ID and pulls out that object so that part is not a problem. It's what is going into the array of objects:
QuestionsSetup: function(gameType) {
// Setup Resources
var c = this.View.children;
var player1qs = [];
var leftQ = 0;
var rightQ = 0;
var maxQValue = 50;
var minQValue = 1;
// Fill array with questions
for (var i = 0; i < 5; i++) {
// Build a random question with numbers between 1 and 50
// Build Question Text to output to user
// Generate correct answers based on generated question
// Generate unsorted, incorrect answers and add them to an array
//Place Questions into object
questions.qId = i;
questions.leftQ = leftQ;
questions.rightQ = rightQ;
questions.correctAnswer = correctAnswer;
questions.allAnswers = sortedAnswers;
questions.questionText = questionText;
//Add to array of questions
player1qs.push(questions);
}
}
This does add them to an array but when adding a new object it also changes the values of the existing objects in the array so they all come out the same no matter which one I pull out later. The questions object is declared in it's own file in a models folder. Is there any way, at the start of each loop, to tell the application I want new empty questions object as opposed to referencing the existing ones? I know that you can in similar back end languguages so I refuse to beleive that something so simple doesn't exist in JavaScript too?
Declaring a variable for each array item is definitely missing.
QuestionsSetup: function(gameType) {
// Setup Resources
var c = this.View.children;
var player1qs = [];
var leftQ = 0;
var rightQ = 0;
var maxQValue = 50;
var minQValue = 1;
// Fill array with questions
for (var i = 0; i < 5; i++) {
var tempQuestion = {
qId: i,
leftQ: leftQ,
rightQ: rightQ,
correctAnswer: correctAnswer,
allAnswers: sortedAnswers,
questionText: questionText
}
// ...
//Add to array of questions
player1qs.push(tempQuestion);
}
}
Using a separate closure inside a loop also might be a good idea.
do this:
for (var i = 0; i < 5; i++) {
let questions = {};
// the rest....
you need to define the object first.
Maybe you should just initialize the questions object before initializing its properties, so the code should look like this:
//Place Questions into object
questions = {};
questions.qId = i;
questions.leftQ = leftQ;
questions.rightQ = rightQ;
questions.correctAnswer = correctAnswer;
questions.allAnswers = sortedAnswers;
questions.questionText = questionText;
//Add to array of questions
player1qs.push(questions);

How to dynamically add object to array (closure in loop)

I read couple posts about the closure in loop but still not really get it how to apply to my situation.
I have three feed urls defined in HTML and using JavaScript promise to return the response when it's ready without blocking the UI. I am able to get two blog entries data per feed url. Now, each returned blog entry has its published date and I would like to sort them from latest to oldest. However, I keep getting the last value when I pushed the object to array. I know this is something to do with closure and since I'm not familiar with closure, I have difficulty to solve this problem. Any help is great appreciated!
var itemArray = [];
var entryObj = {};
promise.then(function (response) {
var parser = new DOMParser();
xml = parser.parseFromString(response, "text/xml");
var items = xml.getElementsByTagName("item");
for (var x = 0; x < items.length && x < limits; x++) {
title = items[x].getElementsByTagName("title")[0].innerHTML;
link = items[x].getElementsByTagName("link")[0].innerHTML;
pubDate = items[x].getElementsByTagName("pubDate")[0].innerHTML;
creator = items[x].getElementsByTagNameNS("http://purl.org/dc/elements/1.1/", "creator")[0].innerHTML;
entryObj.title = title;
entryObj.link = link;
entryObj.pubDate = pubDate;
entryObj.creator = creator;
itemArray.push(entryObj);
// output: all 6 objects contain last value
console.log(itemArray);
}
});
In short : Move the object creation inside the loop.
It's nothing to do with closure. The issue is, you are pushing the same object.
You need a new object to be pushed. So create the object inside the for loop. So that every time you get a new object and it gets pushed to the array.
Code-
var itemArray = [];
promise.then(function (response) {
var parser = new DOMParser();
xml = parser.parseFromString(response, "text/xml");
var items = xml.getElementsByTagName("item");
for (var x = 0; x < items.length && x < limits; x++) {
var entryObj = {};
title = items[x].getElementsByTagName("title")[0].innerHTML;
link = items[x].getElementsByTagName("link")[0].innerHTML;
pubDate = items[x].getElementsByTagName("pubDate")[0].innerHTML;
creator = items[x].getElementsByTagNameNS("http://purl.org/dc/elements/1.1/", "creator")[0].innerHTML;
entryObj.title = title;
entryObj.link = link;
entryObj.pubDate = pubDate;
entryObj.creator = creator;
itemArray.push(entryObj);
// output: Now all values are unique
console.log(itemArray);
}
});
Move var entryObj = {}; into your for loop.

Create variables based on array

I have the following array and a loop fetching the keys (https://jsfiddle.net/ytm04L53/)
var i;
var feeds = ["test_user_201508_20150826080829.txt:12345","test_user_list20150826:666","test_list_Summary20150826.txt:321"];
for (i = 0; i < feeds.length; i++) {
var feed = feeds[i];
alert(feed.match(/\d+$/));
}
The array will always contain different number of keys, What I would like to do is either use these keys as variables and assign the value after the : semicolon as its value or just create a new set of variables and assign the values found on these keys to them.
How can I achieve this? so that I can then perform some sort of comparison
if (test_user > 5000) {dosomething}
update
Thanks for the answers, how can I also create a set of variables and assign the array values to them? For instance something like the following.
valCount(feeds.split(","));
function valCount(t) {
if(t[0].match(/test_user_.*/))
var testUser = t[0].match(/\d+$/);
}
Obviously there is the possibility that sometimes there will only be 1 key in the array and some times 2 or 3, so t[0] won't always be test_user_
I need to somehow pass the array to a function and perform some sort of matching, if array key starts with test_user_ then grab the value and assign it to a define variable.
Thanks guys for all your help!
You can't (reasonably) create variables with dynamic names at runtime. (It is technically possible.)
Instead, you can create object properties:
var feeds = ["test_user_201508_20150826080829.txt:12345","test_user_list20150826:666","test_list_Summary20150826.txt:321"];
var obj = {};
feeds.forEach(function(entry) {
var parts = entry.split(":"); // Splits the string on the :
obj[parts[0]] = parts[1]; // Creates the property
});
Now, obj["test_user_201508_20150826080829.txt"] has the value "12345".
Live Example:
var feeds = ["test_user_201508_20150826080829.txt:12345","test_user_list20150826:666","test_list_Summary20150826.txt:321"];
var obj = {};
feeds.forEach(function(entry) {
var parts = entry.split(":");
obj[parts[0]] = parts[1];
});
snippet.log(obj["test_user_201508_20150826080829.txt"]);
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
You can do it like this, using the split function:
var i;
var feeds = ["test_user_201508_20150826080829.txt:12345","test_user_list20150826:666","test_list_Summary20150826.txt:321"];
for (i = 0; i < feeds.length; i++) {
var feed = feeds[i];
console.log(feed.split(/[:]/));
}
This outputs:
["test_user_201508_20150826080829.txt", "12345"]
["test_user_list20150826", "666"]
["test_list_Summary20150826.txt", "321"]
Use the split method
var feeds = ["test_user_201508_20150826080829.txt:12345","test_user_list20150826:666","test_list_Summary20150826.txt:321"];
feedMap = {}
for (i = 0; i < feeds.length; i++) {
var temp = feeds[i].split(':');
feedMap[temp[0]] = temp[1];
}
Yields:
{
"test_user_201508_20150826080829.txt":"12345",
"test_user_list20150826":"666",
"test_list_Summary20150826.txt":"321"
}
And can be accessed like:
feedMap["test_user_201508_20150826080829.txt"]
Here is a codepen
it is not very good idea but if you really need to create variables on-the-run here's the code:
for (i = 0; i < feeds.length; i++)
{
var feed = feeds[i];
window[feed.substring(0, feed.indexOf(":"))] = feed.match(/\d+$/);
}
alert(test_user_201508_20150826080829)
Of course you cannot have any variable-name-string containing banned signs (like '.')
Regards,
Michał

Dynamically create variables of a object

I am taking a json file and reorganizing it as a object in a new format (Not the same formatting as the json file I am reading, as I want to group variables differently) so I can use it. This requires creating a lot of variables with names that are unknown in advance.
I can dynamically create a new variable in my project like this:
object[variablename]
However, I would like to be able to do things like this
library[musicLibrary.Key].name = musicLibrary.alblum;
and
library[musicLibrary.Key].songs.[musicLibrary.title].name = musicLibrary.song;
Is there any way I can possibly do this?
My current looping code for the json looks like this:
var library = {};
for(var i = 0; i < musicList.songs.length; i++) {
//read json and reorganise it into a object
}
for(var i = 0; i < musicList.songs.length; i++) {
var key = musicLibrary.Key;
library[key] = library[key] || {};
library[key]['name'] = musicLibrary.alblum;
library[key]['songs'] = library[key]['songs'] || {};
library[key]['songs'][musicLibrary.title] = library[key]['songs'][musicLibrary.title] || {};
library[key]['songs'][musicLibrary.title]['name'] = musicLibrary.song;
}

Categories

Resources