This is a function that removes sensitive information from a JSON object before it gets returned to the client. The data that's being passed into the function would either be a JSON object or an array of JSON objects. Why would this function not work?
I know that there are other solutions to the problem, but this is annoying my brain.
I have logged plenty of information in this function and even though JavaScript is asynchronous the functions are running in the order that they should - the recursion is finishing before the final return statement is hit.
The issue right now is that even though everything seems to be working and the delete operator is returning true, the attributes being deleted are still present when the function finally returns.
Example data which is being fetched from MongoDB:
[
{
'id': '1',
'name': 'John',
'password': 'test123',
'emailAddress': 'john#example.com',
'emailAddressVerificationCode': 'A897D'
},
{
'id': '2',
'name': 'Andrew',
'password': 'test123',
'emailAddress': 'andrew#example.com',
'emailAddressVerificationCode': '90H8D'
},
{
'id': '3',
'name': 'Matthew',
'password': 'test123',
'emailAddress': 'matthew#example.com',
'emailAddressVerificationCode': '56C7C'
}
]
Any thoughts would be appreciated.
UserService.cleanJSON = (data) => {
if (Array.isArray(data)) {
for (let i = 0; i < data.length; i++){
data[i] = UserService.cleanJSON(data[i]);
}
} else {
if (data.password) delete data.password;
if (data.emailAddressVerficationCode) delete data.emailAddressVerficationCode;
if (data.mobileNumberVerificationCode) delete data.mobileNumberVerificationCode;
if (data.accountType) delete data.accountType;
}
return data;
};
You are probably using Mongoose or any other ODM, right?
If so, you have to know that you can not change the results unless you call the method .lean() (http://mongoosejs.com/docs/api.html#query_Query-lean).
Mongoose keeps the model safe from any modifications unless you detach the result.
Remove the comma after the last curly bracket in your JSON.
Related
I am receiving a json response from an API call. I need to store its keys, and create an array of an object. I am intending to this array of an object is created dynamically no matter the keys of the response.
I've already got the keys like this:
const json_getAllKeys = data => {
const keys = data.reduce((keys, obj) => (
keys.concat(Object.keys(obj).filter(key => (
keys.indexOf(key) === -1))
)
), [])
return keys
}
That returned an array (using a sample json):
['name','username', 'email']
But I am trying to use that array to create an array of object that looks like this one
[
{
name: "name",
username: "username",
email: "Email",
}
];
I've been trying mapping the array, but got multiple objects because of the loop, and I need a single one to make it work.
keys.map(i=>({i:i}))
[
{ i: 'id' },
{ i: 'name' },
{ i: 'username' },
{ i: 'email' }
]
Any hint would be useful!
Thanks in advance :D
What you're looking for is Object.fromEntries, which is ECMA2019, I believe, so available in Node >=14 and will be provided as a polyfill if you employ babel.
I can't quite discern what your reduce should produce, but given the sample input, I would write
const input = ['name','username', 'email'];
const result = Object.fromEntries(input.map(name => ([name, name])));
// result == { name: 'name', username: 'username', email: 'email' }
You're definitely on the right track. One thing to remember is the map function will return the SAME number of output as input. So in your example, an array of 3 returns an array of 3 items.
For this reason, map alone is not going to give you what you want. You may be able to map => reduce it. However, here is a way using forEach instead. This isn't a strictly functional programming style solution, but is pretty straight forward and depending on use case, probably good enough.
let keys = ['name','username', 'email'] //you have this array
const obj = {}; // empty object to hold result
keys.forEach(i => {
obj[i] = i; // set the object as you want
})
console.log(obj); // log out the mutated object
// { name: 'name', username: 'username', email: 'email' }
I'm building a twitter bot that takes input of someone that DM's my account, and then will output the received DM's into tweet. I'm using twit package from npm. The question is, how do you extract the id's from the output, and then use the id's in another function in order to post the tweet, using? (note that I'm currently using console.log as the tweet for now).
Input command to check the direct messages
var listMsg = T.get('direct_messages/events/list', {
count: '50'
}, function(data, response) {
console.log(response)
Output in terminal (the multiple scope inside the events array)
{
events: [
{
type: 'message_create',
id: '1275746339314216965', //take this
created_timestamp: '1592996604170',
message_create: [Object]
},
{
type: 'message_create',
id: '1274664227584671750', //and this
created_timestamp: '1592738608629',
message_create: [Object]
}
]
}
Getting the content of a direct message
var getMsg = T.get('direct_messages/events/show', {
id:'1274664227584671750' //put it to this
}, function(data, response) {
//console.log(response)
let dm = response.event.message_create.message_data
console.log(dm) //and print the message here
The content of the direct message
{
text: 'Abcd',
entities: { hashtags: [], symbols: [], user_mentions: [], urls: [] }
}
I want to get the id's as a let just like in the third code block.
You can simply use the map array function to transform the object like this
events.map( function(e) { return e.id}) or you can use es6 syntax events.map(e=> e.id)
both would return an array like this
["1275746339314216965", "1274664227584671750"]
These could be joined into into a string like so
events.map(e=> e.id).join(",")
returning
"1275746339314216965,1274664227584671750"
map() is a great function try playing around with map reduce and filter to really improve your programming. There's a great article on them here https://medium.com/poka-techblog/simplify-your-javascript-use-map-reduce-and-filter-bd02c593cc2d
Of course you could do also use a good old fashioned for loop, but think that would be a bit verbose and unnecessary (the software equivalent of making your own hammer)
e.g.
var ids = []
for(var event of events) {
ids.push(event.id)
}
I am implementing a restful api to do stuff just with a local file:
data.js:
let store = {
posts: [
{
id: 1,
name: 'Top 10 ES6 Features every Web Developer must know',
url: 'https://webapplog.com/es6',
text: "This essay will give you a quick introduction to ES6. If you don’t know what is ES6, it’s a new JavaScript implementation.",
comments: [
{ text: 'Cruel…..var { house, mouse} = No type optimization at all' },
{ text: 'I think you’re undervaluing the benefit of ‘let’ and ‘const’.' },
{ text: '(p1,p2)=>{ … } ,i understand this ,thank you !' }
]
},
{
id: 2,
name: 'anotherPost',
url: 'https://webapplog.com/es6',
text: "This essay will give you a quick introduction to ES6. If you don’t know what is ES6, it’s a new JavaScript implementation.",
comments: [
{ text: 'Cruel…..var { house, mouse} = No type optimization at all' },
{ text: 'I think you’re undervaluing the benefit of ‘let’ and ‘const’.' },
{ text: '(p1,p2)=>{ … } ,i understand this ,thank you !' }
]
}
]
}
module.exports = store;
For example here´s how I do a Post request to create another post:
router.post('/', (req, res) => {
data.posts.push({
id: req.body.id,
name: req.body.name,
url: req.body.url,
text: req.body.text,
comments: [
req.body.comments
]
})
res.send(data.posts)
})
Or here´s how I delete a post (i actually add it the id property in order to do this, although minutes later i found out it wasn´t neccesary, but because of it it wasn´t the reason it came up the creation of this question)
router.delete('/:postId', (req, res) => {
const post_id = req.body.id;
const index = post_id -1;
data.posts.splice(index, 1);
res.send(data.posts)
})
So when I try to do the put route i came up with this, although later i also found out i could just use data.posts[index].name = etc... but I decided to open this question because i have really curiosity in how something can this could work (obviously something similar since the following code does not work):
data.posts.filter(post => {
post.id === req.params.postId;
}).then(post => {
post.id = req.body.id,
post.name = req.body.name,
post.url = req.body.url,
post.text = req.body.text,
post.comments = [
req.body.comments
]
})
What am trying to do there is once the correct post has been filtered, then modify the properties of that post. I´ve been doing javascript for months but i have always been blindly following tutorials and never stop to actually learn how callbacks work or how that code is not possible. But because i see similar code to work (callbacks in express), i was wondering if somebody could give some direction.
As i said i already have the simple solution sorted it out but i am very curious in how i could so something like that with the filter function (or just educate me in how this things works)
Since the Array#filter method is synchronous and returns the filtered array, you can chain the Array#map function to it in order to transform the elements of the filtered array. There's no need for a "callback" or promise in the sense that the code is all synchronous ... for iterative methods like map and filter, the function argument is typically called an "iteratee".
So for your last code block, you can simply do something like this:
const filteredAndModifiedPosts = data.posts.filter(post => {
return post.id === req.params.postId;
}).map(post => {
post.id = req.body.id,
post.name = req.body.name,
post.url = req.body.url,
post.text = req.body.text,
post.comments = [
req.body.comments
]
return post
})
First - you could use find() method instead of filter() method to find a single element in an array. filter() returns a new array of elements that satisfied your testing function, while find() returns a single element - the first one that satisfied the testing function. You can see the difference on this basic example:
data.posts.filter(post => post.id === req.params.postId); // [{id: 123}, ...]
data.posts.find(post => post.id === req.params.postId); // {id: 123}
Next - you are using the then() function incorrectly, because you are trying to apply it to the result of the filter() function call, which is, as I explained already, an Array not a Promise. Here, you seem to belive the filter() function is asynchronous, but that is incorrect. So what you could simply do to find your desired post and then change its properties is this:
const post = data.posts.find(post => post.id === req.params.postId);
post.id = req.body.id;
post.name = req.body.name;
post.url = req.body.url;
post.text = req.body.text;
post.comments = req.body.comments;
This is what I'd like to do in an Angular factory:
app.factory('dataService', function () {
return {
data: ['5', '10', '20', '50', '100', '200'],
selectedData: data[0],
},
},
)
Basically, I want to initialize selectedData to one of the items of predefiend data array. This code returns data is not defined. If I use this.data[0], I get the error: Cannot read property '0' of undefined. So, how do I refer to data here?
Try storing the object locally, then setting the value, and finally returning:
app.factory('dataService', function () {
var obj = { data: ['5', '10', '20', '50', '100', '200'] };
obj.selectedData = obj.data[0];
return obj;
}
)
You cannot reference data as you are defining the object.
That's not how this works.
If you really are sure that you want an object that has final values, then the answer from Troels Larsen is the way to go. However, in many applications, its wise to have objects that can get updated data for you at any time. It is difficult to show-and-tell without knowing your app, but doing that would look something like this...
app.factory('dataService', function () {
var result = {
data: ['5', '10', '20', '50', '100', '200'],
getSelectedData: function (index) {
return this.data[index];
}
}
return result;
})
Then anywhere else, you can get access to exactly what you want - which is especially useful in situations where that data array may not be stable.
In my first function, I am getting a few pieces of information and pushing them to my object.
autoArry.push({
id: countTxns,
txnID: txnID,
account: buyersAccount,
data1: '',
data2: '',
data3: ''
});
At this point, I dont have the information from data1, data2, or data3 but I created them in the object anyway.
Later in my script, I want to be able to fill in those data values when i collect it throughout other functions.
The one thing that I will have that is the same in every function is the txnID.
I assume I will have to Map that somehow and then add additional data that way.
Would anyone be able to explain how I could do this?
Thanks Much
Iterate and check for a match :
function otherFunction(txnID) {
for (var i=0; i<autoArray.length; i++) {
if (autoArray[i].txnID == txnID) {
autoArray[i].data1 = 'something 1';
autoArray[i].data2 = 'something 2';
autoArray[i].data3 = 'something 3';
}
}
}