calling firebase inside an forEach makes the iteration not work - javascript

Goal:
Im trying to make an array of objetcs including 3 informations: id, title and imageUri. But when i try to get the imageUri value from firebase(an image download URL from firebase) to download this image in another component, the iteration of forEach freezes. Thank you for your time :)
Warning:[Unhandled promise rejection: TypeError: JSON.stringify cannot serialize cyclic structures.]
observation: When i remove the firebase part imageUri: firebase..., the whole thing works!
the function:
processData = ( data ) => {
console.log('---------data received from loadData(Main.js:70)--------\n', data)
var localProcessedData = [];
Object.entries(data).forEach( ([key, value]) => {
var event = {
id: key,
title: Object.getOwnPropertyDescriptor(value, "eventTitle").value,
imageUri: firebase.storage().ref('events/active/' + key + '/image').getDownloadURL()
}
localProcessedData.push(event);
})
this.setState({
processedData: localProcessedData,
eventsDataIsLoaded: true,
})
}
The type of params the function recieve:
Object {
"-M-I83aV9t1fezOsBn17": Object {
"active": true,
"created": "2020-02-05T02:18:30.772Z",
"description": "Olimpiadas Inter Atletica",
"eventTitle": "oia",
"location": "Uberlandia",
"owner": "p87xn6x8DZTwb6qyTadhkk3UxJV2",
"price": "130",
"startDate": "15",
"time": "14",
"updated": "2020-02-05T02:18:30.772Z",
},
"-M-KlUH-zQhnIhb6wMH8": Object {
"active": true,
"created": "2020-02-05T14:34:20.399Z",
"description": "Cia 2020",
"eventTitle": "Cia",
"location": "Uberlandia",
"owner": "p87xn6x8DZTwb6qyTadhkk3UxJV2",
"price": "130340",
"startDate": "15",
"time": "14",
"updated": "2020-02-05T14:34:20.399Z",
}
}
Expected:
My goal is to transform that whole data in an array like this:
Array [
Object {
"id": "-M-I83aV9t1fezOsBn17",
"title": "oia",
"imageUri": "image url from firebase"
},
Object {
"id": "-M-KlUH-zQhnIhb6wMH8",
"title": "Cia",
"imageUri": "image url from firebase"
}
]

Based on firebase documentation. FIrebase Storage getDownloadUrl is a promise
https://firebase.google.com/docs/reference/js/firebase.storage.Reference.html#get-downloadurl
solution is to implement an async/await
async processData = ( data ) => {
console.log('---------data received from loadData(Main.js:70)--------\n', data)
var localProcessedData = [];
Object.entries(data).forEach( async([key, value]) => {
var event = {
id: key,
title: Object.getOwnPropertyDescriptor(value, "eventTitle").value,
imageUri: await firebase.storage().ref('events/active/' + key + '/image').getDownloadURL()
}
localProcessedData.push(event);
})
this.setState({
processedData: localProcessedData,
eventsDataIsLoaded: true,
})
}
this code is not yet tested.

Related

Find object and remove specific array value inside it with lodash

I have this array of object, and I want to remove specific value from "subscriber" array
[
{
"slug": "just",
"subscriber": ["0610988037", "1107405573"]
},
{
"slug": "test",
"subscriber": ["1107405573"]
}
]
expected output
[
{
"slug": "just",
"subscriber": ["0610988037"]
},
{
"slug": "test",
"subscriber": ["1107405573"]
}
]
what I've tried this so far
const index = _.findIndex(subs, { slug: "just" });
const newSubscriber = subs[index].subscriber.filter(
(i) => i !== "1107405573"
);
subs[index].subscriber = newSubscriber;
the above code is work fine as expected but I don't think it's a good way
As the question leaves a few points open, the following is written under the assumptions that:
there can be several objects with arr[i].slug==="test"
and several with arr[i].slug!=="test"
all values found in arr[i].subscribers of a "test-object" will be removed from all arr[j].subscribers arrays of "non-test-objects",
"test"-objects will remain unchanged.
const arr = [ {
"slug": "test",
"subscriber": ["555666","333","999"]
},
{
"slug": "just",
"subscriber": ["0610988037", "1107405573", "333"]
},
{
"slug": "something else",
"subscriber": ["0610988037", "123", "987"]
},
{
"slug": "test",
"subscriber": ["1107405573","123"]
}
];
const filt=arr.reduce((a,c)=>(c.slug==="test" && c.subscriber.forEach(s=>a[s]=1),a),{}),
res =arr.map(el=>({...el, subscriber:el.slug!=="test" ? el.subscriber.filter(s=>!filt[s]) : el.subscriber}))
console.log(res)
Update:
Taking into account the latest information from OP's comment:
all arr[i].slug values are unique
so, there can at most be one object with arr[i].slug=="test"
all values found in arr[i].subscribers of the "test-object" will be removed from all arr[j].subscribers arrays of "non-test-objects",
the same subscriber values can appear in several objects
the "test"-object, if it exists, will remain unchanged.
The test input will now look slightly different but will still work with the same script:
const arr = [
{
"slug": "just",
"subscriber": ["0610988037", "1107405573", "333"]
},
{
"slug": "something else",
"subscriber": ["0610988037", "123", "987"]
},
{
"slug": "test",
"subscriber": [ "555666","333","999", "1107405573","123"]
}
];
const filt=arr.reduce((a,c)=>(c.slug==="test" && c.subscriber.forEach(s=>a[s]=1),a),{}),
res =arr.map(el=>({...el, subscriber:el.slug!=="test" ? el.subscriber.filter(s=>!filt[s]) : el.subscriber}))
console.log(res)

How to get attribute value from JSON and write it in file in specific format using node.js

I have a test.json file and It's in below format and I just want to get link value from that file:
Input file from File System:
{
"5cacd1333105": {
"type": "CORR-ID",
"environment": "amazon",
"tags": [
{
"name": "EC-6S0005704A8324S98020",
"source": "amazonstage2ma_paymentapiplatserv#TOKEN",
"flags": [
"FLAG_DYNAMIC_VALUE",
"FLAG_ID_LOOKUP_SUPPORTED"
]
}
],
"callSummary": [
{
"colo": "lvs",
"pool": "slingshotrouter",
"machine": "stage21007",
"apiName": "GET",
"status": "0",
"duration": 13400.0,
"calls": null,
"hints": null,
"msgTime": 1574314991130,
"link": "https://www.amazon.qa.pilot.com/Tid-942342192424j2j234"
},
{
"colo": "lvs",
"pool": "slingshot",
"machine": "stage21029",
"apiName": "GET",
"status": "0",
"duration": 13368.0,
"calls": null,
"hints": null,
"msgTime": 1574314991162,
"link": "https://www.amazon.qa.pilot.com/Tid-12342342i842424j2j234"
},
{
"colo": "lvs",
"pool": "msmaster_userbridgedomainserv",
"machine": "amazon1int-g_userbridgedomainserv_22",
"apiName": "POST",
"status": "0",
"duration": 15.0,
"calls": null,
"hints": null,
"msgTime": 1574315001625,
"link": "https://www.amazon.qa.pilot.com/Tid-02341723424i842424j2j290"
}
],
"partial": false
}
}
I wanna get the below details from above file:
"https://www.amazon.qa.pilot.com/Tid-942342192424j2j234"
"https://www.amazon.qa.pilot.com/Tid-12342342i842424j2j"
"https://www.amazon.qa.pilot.com/Tid-02341723424i842424"
I just want to write into test.js file as below format.
module.exports =
{
fileNames:[
'https://www.amazon.qa.pilot.com/Tid-942342192424j2j234',
'https://www.amazon.qa.pilot.com/Tid-12342342i842424j2j',
'https://www.amazon.qa.pilot.com/Tid-02341723424i842424'
]
}
I don't know how to get those details. Can someone please share me some input on this?
It looks like 5cacd1333105 is a dynamic key, so it might change, and there might be more than one random key like that, so you can use a for... in loop like this to loop each key (prop) in the object:
const d = require('./test.json');
for(let prop in d){
console.log(d[prop])
}
Then you can see that the only relevant property is callSummary array because it contains the link data. Therefore you can loop the array to extract the link data.
for(let prop in d){
const obj = d[prop];
const links = obj.callSummary.map(({link}) => link);
console.log(links);
}
The above uses destructuring inside a .map callback to extract the link string from the objects inside callSummary, returning an array of link strings in links.
However, we still need to take into account the general case of multiple links due to the outer for... in loop.
To combine the links into a single array, you can declare links outside the loops as an empty array, and just push to that array, like this:
const links = [];
for(let prop in d){
const obj = d[prop];
links.push(obj.callSummary.map(({link}) => link));
}
console.log(links);
Finally, you want to write that data into a file. You can use either fs or you could spawn / execute a command line program from within your node.js script. See https://nodejs.org/api/fs.html#fs_fs_writefile_file_data_options_callback on how to use fs.writeFile or use child_process e.g.
const d = require('./test.json');
const path = require('path');
const { spawn } = require( 'child_process' );
const links = [];
for(let prop in d){
const obj = d[prop];
links.push(obj.callSummary.map(({link}) => link));
}
const filename = `links-${Date.now()}.js`;
console.log(`Outputting links to ${filename}`);
const echo = spawn( 'echo', [ `
module.exports =
{
fileNames:[
${JSON.stringify(links, false, 2)}
]
}
`, '>', path.join(process.cwd(), filename) ] );
Note the use of backticks. (I didn't test that last bit, but it should work).
You have not shared how you are acquiring this data, but since you added a tag for node.js, I am assuming you are doing this on the server side.
After you make sure the data you received is in JSON format (using JSON.parse) and it is valid, to get the specific fields you require, you can do the following:
let links = [];
let callSummary = json['5cacd1333105'].callSummary
for (let index = 0; index < callSummary.length; index++) {
let call = callSummary[index];
if (call && call.link) {
links.push(call.link);
}
}
After this, you will have al lthe links in the array links and you can do whatever you please with them.
This code have a little risk, but it's work in your situation
const data = {
"5cacd1333105": {
"type": "CORR-ID",
"environment": "amazon",
"tags": [
{
"name": "EC-6S0005704A8324S98020",
"source": "amazonstage2ma_paymentapiplatserv#TOKEN",
"flags": [
"FLAG_DYNAMIC_VALUE",
"FLAG_ID_LOOKUP_SUPPORTED"
]
}
],
"callSummary": [
{
"colo": "lvs",
"pool": "slingshotrouter",
"machine": "stage21007",
"apiName": "GET",
"status": "0",
"duration": 13400.0,
"calls": null,
"hints": null,
"msgTime": 1574314991130,
"link": "https://www.amazon.qa.pilot.com/Tid-942342192424j2j234"
},
{
"colo": "lvs",
"pool": "slingshot",
"machine": "stage21029",
"apiName": "GET",
"status": "0",
"duration": 13368.0,
"calls": null,
"hints": null,
"msgTime": 1574314991162,
"link": "https://www.amazon.qa.pilot.com/Tid-12342342i842424j2j234"
},
{
"colo": "lvs",
"pool": "msmaster_userbridgedomainserv",
"machine": "amazon1int-g_userbridgedomainserv_22",
"apiName": "POST",
"status": "0",
"duration": 15.0,
"calls": null,
"hints": null,
"msgTime": 1574315001625,
"link": "https://www.amazon.qa.pilot.com/Tid-02341723424i842424j2j290"
}
],
"partial": false
}
};
const jsonDAta = JSON.stringify(data,null,null);
const resArr = (jsonDAta.match(/"link":"[^"]+"/g)||[]).map(el=>JSON.parse(`{${el||''}}`).link)
console.log(resArr);

I need remove unnecessary json objects form my result json file using javascript

I have result json file with 10000 of lines. inside the one array object there are some unnecessary json object i need remove. I have tried so many ways but it's didn't work for me. herewith the piece line of json file
[
{
"product_id": "easybridge",
"errors": []
},
{
"product_id": "learningstudio",
"errors": []
},
{
"product_id": "pearsontestprep",
"errors": []
},
{
"product_id": "productization",
"errors": []
},
{
"product_id": "equella",
"errors": [
{
"property": "instance.test_ids[1]",
"message": "requires property \"maintenance\"",
"schema": {
"$id": "#/properties/test_ids/items",
],
"properties": {
"trend": {
"$id": "#/properties/test_ids/items/properties/trend",
"examples": [
true
]
},
"display": {
"$id": "#/properties/test_ids/items/properties/display",
"type": "boolean",
"examples": [
true
]
},
"test_id": {
"$id": "#/properties/test_ids/items/properties/test_id",
"type": "string",
},
"test_name": {
"$id": "#/properties/test_ids/items/properties/test_name",
"type": "string",
},
"maintenance": {
"$id": "#/properties/test_ids/items/properties/maintenance",
"type": "boolean",
]
},
"instance": {
"trend": false,
"display": false,
"test_id": "8597ae3c-e2a9-45c7-b279-bde1710681be",
"test_name": "Equella Pearsonresearch Ping Test",
"nrAlertStatus": "enabled",
"test_locations": [
{
"alert_state": false,
"location_name": "AWS_US_WEST_2",
"location_label": "Portland, OR, USA",
"included_to_health": false
}
],
"included_to_health": false,
"critical_alert_threshold": 60
},
"name": "required",
"argument": "maintenance",
"stack": "instance.test_ids[1] requires property \"maintenance\""
{
"product_id": "easybridge",
"errors": []
},
I just need only
{
"product_id": "equella",
"errors": [
{
"property": "instance.test_ids[1]",
"message": "requires property \"maintenance\"",
}
},
if the errors json array is not empty. i don't need even this json how can i remove "schema" json object and other unnecessary json object and arrays specially "schema" json object using java script or java. please help
Loop through the array, look at each object, and create a new array by copying over the data you need.
For instance, I'm taking it you don't care about an object if its array of errors is empty, and that you don't care about the schema ever:
let newJSON = [];
//Assume the json variable is the parsed JSON file you posted.
for (let element of json) {
//Must have at least one error
if (element.errors.length > 0) {
//Create a new object
let newObj = {
"product_id" : element.product_id,
"errors" : []
};
//Add each errror
for (let error of element.errors) {
//Only copy across what we need
newObj.errors.push({
"property" : error.property,
"message" : error.message
});
}
//Add object to our new array of JSON
newJSON.push(newObj);
}
}
//newJSON is your processed JSON output
The easiest solution can be:
const records = [{
"product_id": "learningstudio",
"errors": []
},
{
"product_id": "pearsontestprep",
"errors": []
},
{
"product_id": "equella",
"errors": [{
"property": "instance.test_ids[1]",
"message": "requires property \"maintenance\"",
"schema": {
"$id": "#/properties/test_ids/items",
}
}]
}];
const filteredRecords = records.map((record) => {
record.errors = record.errors.map((error) => {
return {property: error. property, message: error.message};
});
return record;
});
console.log(filteredRecords);
You can use map and destructuring assignment to capture only desired properties
let json = [{"product_id": "equella", "errors": [{"property": "instance.test_ids[1]","message": "requires property \"maintenance\"",'xyz': 'not needed','useless': 'not needed',},{'xyz': 'not needed',}]},]
let op = json.map(({product_id,errors}) =>{
let { property, message } = errors[0]
return { product_id, errors: {property,message}}
})
console.log(op)

Can't acces my JSON files with ES6

I'm working on a little chat application where you can click on different contacts and see / send messages.
I have this users.json file with the contacts:
{
"results":[
{
"gender":"female",
"name":{
"title":"Ms",
"first":"Leonie",
"last":"Otto"
},
"location":{
"street":"3076 raiffeisenstraße",
"city":"meißen",
"state":"sachsen-anhalt",
"postcode":62480
},
"email":"leonie.otto#example.com",
"login":{
"username":"bigwolf465",
"password":"stephane",
"salt":"Ip5qcgs5",
"md5":"fe5df54750c64b7c5d54c92f0cb91f11",
"sha1":"17d255fb64135b5e247a4ef5554557a1d2a8881e",
"sha256":"341d750fce611b853b4f27d485f10ef9f9c3add4de12a7fbf838a1fd2d5168a9"
},
"dob":"1955-01-08 01:03:55",
"registered":"2012-07-07 16:42:10",
"phone":"0265-7006038",
"cell":"0178-0561111",
"id":{
"name":"",
"value":null
},
"picture":{
"large":"https://randomuser.me/api/portraits/women/8.jpg",
"medium":"https://randomuser.me/api/portraits/med/women/8.jpg",
"thumbnail":"https://randomuser.me/api/portraits/thumb/women/8.jpg"
},
"nat":"DE",
"status": "online"
},
{
"gender":"female",
"name":{
"title":"Miss",
"first":"Olive",
"last":"Wright"
},
"location":{
"street":"2912 manukau road",
"city":"timaru",
"state":"otago",
"postcode":30721
},
"email":"olive.wright#example.com",
"login":{
"username":"brownrabbit413",
"password":"derek",
"salt":"gRxy7hHq",
"md5":"dc214ffe467373790c8500abd1ff0f8f",
"sha1":"7b7847e1a9e3b3de081e3eeebf972dc5d2b5527a",
"sha256":"1763dff5c43e1cea431d1ad8c1648c586af9d1e1410001d743078af143ce30b9"
},
"dob":"1982-07-01 12:12:29",
"registered":"2016-03-25 19:15:33",
"phone":"(003)-127-5232",
"cell":"(133)-307-2001",
"id":{
"name":"",
"value":null
},
"picture":{
"large":"assets/img/users/233899238.jpg"
},
"nat":"NZ",
"status": "online"
}
I both put them in a list item where I show their name, username and profile picture. This all works out well.
The next I want is that if I click on the specific contact, it shows all their message history.
So as an example for the contact with the username bigwolf465 I use this json file:
{
"ok": true,
"messages": [
{
"type": "message",
"user": "me",
"text": "Can I have this?",
"ts": "1512085950.000216"
},
{
"type": "message",
"user": "other",
"text": "No.",
"ts": "1512085950.218404"
},
{
"type": "message",
"user": "me",
"text": "Ah, perhaps I’ve miscommunicated. I’m asking for it because I want it.",
"ts": "1512085950.000216"
},
{
"type": "message",
"user": "other",
"text": "I understood that, actually.",
"ts": "1512085950.000216"
},
{
"type": "message",
"user": "me",
"text": "I think maybe you’re not hearing me. I’d like it because I want it.",
"ts": "1512085950.000216"
},
{
"type": "message",
"user": "other",
"text": "There's no problem with my hearing. The problem is that your argument is, as the Romans would say:",
"ts": "1512085950.000216"
},
{
"type": "message",
"user": "other",
"text": "Circulus in probando.",
"ts": "1512085950.000216"
}
],
"pin_count": 0
}
I also want to make a list item for these messages, but it doens't seem to work out. This is the JS code I have right now:
const handleContactClick = ({
currentTarget: $li
}) => {
loadContactDetails($li);
};
const loadContactDetails = $li => {
fetch(`./assets/data/messages/${$li.dataset.username}.json`)
.then(r => r.json())
.then(parseContactDetail);
}
const parseContactDetail = messages => {
const $container = document.querySelector(`.messages-list`);
const $li = document.createElement(`li`);
$li.classList.add(`reply`);
$container.appendChild($li);
const $img = document.createElement(`img`);
$img.setAttribute(`src`, `assets/img/me.png`);
$li.appendChild($img);
const $p = document.createElement(`p`);
$p.textContent = `${messages.text}`;
$li.appendChild($p);
}
When I click on the specific contact, it just adds messages with the text "undefined". I don't really know how to fix it, it seems I can't get acces to the JSON file.
Here's the function, fixed:
const parseContactDetail = person => {
const $container = document.querySelector(`.messages-list`);
person.messages.forEach(m => {
const $li = document.createElement(`li`);
$li.classList.add(`reply`);
$container.appendChild($li);
const $img = document.createElement(`img`);
$img.setAttribute(`src`, `assets/img/me.png`);
$li.appendChild($img);
const $p = document.createElement(`p`);
$p.textContent = `${m.text}`;
$li.appendChild($p);
});
}
The function now properly grabs .messages from the passed data object, then loops over the array, creating a <li> for each element.

cannot update an array of elements via a 2d iteration

I have two arrays of object, the first array (printerChart, around 80 elements) is made of the following type of objects:
[{
printerBrand: 'Mutoh',
printerModel: 'VJ 1204G',
headsBrand: 'Epson',
headType: '',
compatibilty: [
'EDX',
'DT8',
'DT8-Pro',
'ECH',
],
},
....
]
The second array (items, around 500 elements) is made of the following type of objects:
[
{
"customData": {
"brand": {
"value": {
"type": "string",
"content": "hp"
},
"key": "brand"
},
"printer": {
"value": {
"type": "string",
"content": "c4280"
},
"key": "printer"
}
},
"name": "DT8 XLXL",
"image": {
"id": "zLaDHrgbarhFSnXAK",
"url": "https://xxxxxxx.net/images/xxxxxx.jpg"
},
"brandId": "xxxxx",
"companyId": "xxxx",
"createdAt": "2018-03-26T14:39:47.326Z",
"updatedAt": "2018-04-09T14:31:38.169Z",
"points": 60,
"id": "dq2Zezwm4nHr8FhEN"
},
...
]
What I want to do is to iterate via the second array and, if the part of the name of an item (i.e. DT8) is included in an element of the array 'compatibility' of the first array, I would like to include a new properties to it from the element of the first array: printerBrand. I have tried but somehow the iteration doesn't take place correctly. This is what I tried:
items.forEach((item) => {
printerChart.forEach((printer) => {
if (printer.compatibilty.some(compatibleElem => (
item.name.includes(compatibleElem)))) {
item.printerBrand = printer.printerBrand;
} else {
item.printerBrand = '';
}
});
});
What am I doing wrong?
You do
items.items.forEach(...)
Shouldn't you be doing
items.forEach(...)
?
I suggest to initialize item.printerBrand with an empty string and use a nested approach of some for getting a brand and to exit the loops, if found.
This prevents to get an empty string even if there is a brand to assign.
items.forEach((item) => {
item.printerBrand = '';
printerChart.some(printer => {
if (printer.compatibilty.some(compatibleElem => item.name.includes(compatibleElem))) {
item.printerBrand = printer.printerBrand;
return true;
}
});
});

Categories

Resources