Parsing json response gives undefined - json

I am using angularfire2 to fetch data from realtime DB. and response comes like below
{"type":"value",
"payload":{
"-LJXFAd_q3Cin64EBc7H":
{"_date":"9-8-2018",
"_deliveryType":"Pick up",
"_estDeliveryTime":"2018-08-10T11:43:57.164Z",
"_location":""}
}}
this on doing
the element inside payload is a key created using push. I wont know it to refer so how do i get the data under "LJXFAd_q3Cin64EBc7H" ?
there are many such entries inside payload and i need to fetch all.
code used to get above is:
getOrderHistory(uid:string){
console.log('start of getOrderHistory with uid:' + uid)
return new Promise((resolve, reject) =>
{
this.db.object("/users/" + uid + "/orders").snapshotChanges().subscribe(
res => {
//console.log('response:' + res)
resolve(res)
},
err => {
console.log(err)
reject(err)
}
)
})
}

Try this, it maps each snapshot to an object that holds its key and values.
this.db.object("/users/" + uid + "/orders").snapshotChanges()
.map(snapshot => {
const key = snapshot.key;
const data = snapshot.payload.val();
return { key, ...data };
})
.subscribe(res => {
resolve(res);
},
err => {
console.log(err);
reject(err);
});

normally, realtime database sends snapshot where you can do snapshot.id to get the id and .data (or .data() I forget at the moment) to get at the payload.
JSON.parse it then iterate it or get at it with dot notation or bracket notation. To get a property:
obj[payload][LJXFAd_q3Cin64EBc7H]
To iterate it:
function eachRecursive(obj)
{
for (var k in obj)
{
if (typeof obj[k] == "object" && obj[k] !== null)
eachRecursive(obj[k]);
else
// do something...
}
}

Related

How to extract key and value from json in fetch method in React Native?

I'm new in React Native. I would like to extract a value from json with fetch to do a simple test to begin. But I don't understand, how to select a particular key from Json. Always, I have undefined return. I tried to modify my code with this post but it doesn't work. I tried to parse before but he didn't want because it's already an object.
This is my code:
checkLogin = () => {
const { name } = this.state;
const { surname } = this.state;
fetch('https://ffn.extranat.fr/webffn/_recherche.php?go=ind&idrch=' + name + '%20' + surname, {
method: 'GET',
}).then((response) => response.json())
.then((responseJson) => {
if (responseJson.ind == 'Individu non trouv\u00e9 !') {
alert("Id incorrect")
}
else {
alert("Id correct");
}
alert(JSON.stringify(responseJson.ind))
}).catch((error) => {
console.error(error);
});
}
This is my JSON format:
[{"iuf":"1366701","ind":"LEBRUN L\u00e9o (2000) H FRA - CN BEAUPREAU","sex":"#1e90ff","clb":"CN BEAUPREAU"}]
I know my request work because when I run this code alert(JSON.stringify(responseJson)).It return the entire json. So I don't know, how to resolve the undefined return.
Regards
Your json is an array, you either need to loop through it if there is multiple items inside, or just use responseJson[0] to read it. So if you want to read your json, your code would look like this :
const checkLogin = () => {
const { name } = this.state;
const { surname } = this.state;
fetch(
"https://ffn.extranat.fr/webffn/_recherche.php?go=ind&idrch=" +
name +
"%20" +
surname,
{
method: "GET"
}
)
.then(response => response.json())
.then(responseJson => {
// Since you have only one object inside your json, you can read the first item with 'responseJson[0]'.
if (responseJson[0].ind == "Individu non trouv\u00e9 !") {
alert("Id incorrect");
} else {
alert("Id correct");
}
alert(JSON.stringify(responseJson[0].ind));
// If you have multiple elements inside your responseJson,
// then here is a loop example :
// responseJson.forEach(item => {
// console.log('item ind = ', item.ind);
// });
})
.catch(error => {
console.error(error);
});
};
Use async await.
const checkLogin = async () => {
const { name } = this.state;
const { surname } = this.state;
const request = await fetch(
"https://ffn.extranat.fr/webffn/_recherche.php?go=ind&idrch=" +
name +
"%20" +
surname)
const response = await request.json();
console.log('result from server', response)
}

JSON object getting damaged when using chrome.storage.local.set

When retrieving a complex JSON object from chrome.storage.local the object is breaking.
mock.json
{
"ThingOne" : [
"a",
"b"
],
"ThineTwo" : [
"a",
"b"
],
"People" : {
"FamilyOne" : {
"AgeOne" : "3",
"AgeTwo" : "8"
}
},
"Hats" : ["blue", "red", "green"]
}
and I am fetching this file (correctly) using
fetch('./mock.json').then(response => {
console.log(response);
return response.json();
}).then(data => {
//data == the whole json file
var data2 = JSON.stringify(data);
chrome.storage.local.set({'StoredJson': data2});
//here this is the result of this code
//console.log(data2.ThingOne[0]);
//outputs => "a"
}).catch(err => {
console.log("Error Reading data " + err);
});
waitfunction();
chrome.storage.local.get('StoredJson', function(result) {
console.log("from get ------"); //outputs below
console.log(result); //{Data: ""{\"ThingOneOne\":[\"a\",\"b\"],\...
console.log(typeof result); //object
console.log(typeof result.ThingOne);//undefined
//https://imgur.com/OF7pVQQ
});
Why is it working when I fetch the object but not when I retrieve it. I have tried storing it after JSON.stringifying it. And I have tried to use it after JSON.parsing it which returns
VM6:1 Uncaught SyntaxError: Unexpected token o in JSON at position 1
at JSON.parse ()
indicating that it is already a JS object.
I have tried using dot notation and bracket notaion it doesn't work. When I store it in the chrome console as var data = {//json here} it works. But not live. StackOverflow: Save json to chrome storage / local storage hasn't helped me. Picture of console
There are multiple problems in the code.
There's no need for JSON.stringify. Just store the data directly.
Both fetch and chrome.storage are asynchronous so your chrome.storage.local.get will run before the data is set and it won't see the correct data.
waitfunction(); won't wait for anything, it won't influence asynchronous code before it or afterwards.
chrome.storage.local.get('StoredJson', callback) reads the data into an object property named StoredJson i.e. you can read the value as result.StoredJson.
Overall, a proper modern solution is to switch to async/await:
(async () => {
try {
const data = await (await fetch('./mock.json')).json();
console.log('Fetched', data);
await writeStorage({StoredJson: data});
const {StoredJson} = await readStorage('StoredJson');
console.log('Stored', StoredJson);
} catch (err) {
console.log(err);
}
})();
function readStorage(key) {
return new Promise(resolve => {
chrome.storage.local.get(key, resolve);
});
}
function writeStorage(data) {
return new Promise(resolve => {
chrome.storage.local.set(data, resolve);
});
}

Is there a way to pass a value from a mysql callback function to the outer function in express?

I'm using express and npm MySQL to develop an API.I have a json request in this format:
{
"payments":[
{
"PolicyNo": "ME3",
"PaymentDate": "2019-04-16T18:00:00.000Z",
},
{
"PolicyNo": "PIN001q",
"PaymentDate": "2019-04-16T18:00:00.000Z",
}]
}
I want to check the database if the policyNo exists before inserting. To avoid the common ERR_HTTP_HEADERS_SENT, I've looped through the payments querying the database with the PolicyNo. If it exists it's pushed into a success array if it doesn't it's pushed into a failed array.
This works perfectly but I can't access these arrays outside the callback.
Here's what I've tried:
router.post('/bla', (req, res)=>{
const values = []
const failedvalues = []
let sql = 'SELECT PolicyNo from pinclientinfo WHERE PolicyNo=?'
req.body.payments.forEach(element => {
connection.query(sql,element.PolicyNo,(err, rows) =>{
if(!err){
if(rows && rows.length > 0){
values.push(element.PolicyNo, element.PaymentDate)
}else{
failedvalues.push(element.PolicyNo)
}
}
})
})
res.json({
failed:failedvalues,
success:values
})
})
Here's the response I'm getting:
{
"failed": [],
"success": []
}
This has some major problems, mostly conceptually.
Firstly the forEach is synchronous will be called payments.length number of times, but the sql query is Asynchronous so it will complete in the future.
I think you are confused between synchronous and asynchronous functions and how they work.
But you can solve this (in your case) atleast two ways.
1) Use the IN syntax and get the array. Iterate over it and do stuff. "SELECT PolicyNo from pinclientinfo WHERE PolicyNo in (...)"
let sql = 'SELECT PolicyNo from pinclientinfo WHERE PolicyNo IN (' + Array(req.body.payments).fill('?').join(',') + ')'
const policies = req.body.payments.map(p => p.PolicyNo);
const values = [];
const failedvalues = [];
connection.query(sql, ...policies, (err, rows) => {
//now check each row..
rows.forEach(element => {
//Not optimized only depicts logic
///do stuff
/// like fill values and failedvalues
if(policies.indexOf(element.PolicyNo) > -1){
values.push(...)
}else{
failedvalues.push(...)
}
});
res.json({
failed: failedvalues,
success: values
})
})
Which will be 1 DB call.
2) The other approach is (not very good) doing multiple db calls and check for count.
let sql = 'SELECT PolicyNo from pinclientinfo WHERE PolicyNo=?'
let count = 0;
req.body.payments.forEach(element => {
connection.query(sql, element.PolicyNo, (err, rows) => {
if (!err) {
if (rows && rows.length > 0) {
values.push(element.PolicyNo, element.PaymentDate)
} else {
failedvalues.push(element.PolicyNo)
}
}
// check If all Complete
count+=1;
if(count === req.body.payments){
//all complete
res.json({
failed: failedvalues,
success: values
})
}
})
})
BUT SERIOUSLY, USE PROMISE. USE ASYNC/AWAIT USE THOSE SWEET LITTLE FEATURES ES6 GIVES YOU
Check out: this post
because connection.query is asynchronous, so return:
{
"failed": [],
"success": []
}
use promise and await you can synchronized resolve mysql data
use Promise.all() you can synchronized resolve list of promise
router.post("/bla", async (req, res) => {
let values = [];
let failedvalues;
let promises = [];
let sql = "SELECT PolicyNo from pinclientinfo WHERE PolicyNo=?";
req.body.payments.forEach(element => {
promises.push(
new Promise(function(resolve, reject) {
connection.query(sql, element.PolicyNo, (err, rows) => {
if (!err) {
if (rows && rows.length > 0) {
values.push(element.PolicyNo, element.PaymentDate);
} else {
failedvalues.push(element.PolicyNo);
}
}
resolve();
});
})
);
});
await Promise.all(promises);
res.json({
failed: failedvalues,
success: values
});
});

how to access nested data by nesting fetch calls?

I'm having trouble understanding the best approach to this.
My goal is to display nested data.
I use fetch on this url - https://horizons-json-cors.s3.amazonaws.com/products.json
which takes me to a page that contains json. inside the json is 3 urls. each url contains the data that I need to get to.
So far, I've accessed the first layer, and now have an array of the item urls. I guess I don't understand how to fetch the data while im inside the outter fetch call.
Here's my code thus far (the result is an array of urls, where each url contains the data I need.) :
componentDidMount() {
console.log('Fetch');
fetch("https://horizons-json-cors.s3.amazonaws.com/products.json")
.then((resp) => (resp.json()))
.then((json) => {
var productUrlArr = [];
for (var i = 0; i < json.length; i++) {
productUrlArr.push(json[i].url);
}
.catch((err) => {
console.log('error', err);
});
}
If you guys could help me out and really walk through how to access the next level of data, I would really, really appreciate it.
You can Fetch Data for Inner URLs this way too,
// 1. Outer Fetch call initiated here
fetch("https://horizons-json-cors.s3.amazonaws.com/products.json")
.then(res => {
return res.json()
})
.then(res => {
// 2. array for storing url's retrieved from response
var urlArray = []
if (res.length > 0) {
// 3. Push url inside urlArray
res.map(data => urlArray.push(data.url))
}
// 4. an array of urls
return urlArray
})
.then(urls => {
// Return an promise which will return "JSON response" array for all URLs.
// Promise.all means “Wait for these things” not “Do these things”.
return Promise.all(urls.map(url => {
// Take url fetch response, return JSON response
return fetch(url).then(res => res.json())
}
))
})
.then(res => {
// Store all objects into array for later use
var objArr = res; return objArr
})
//.then(...)
You have a little error in your code.
It's missing }) before .catch
With it you can use your data in the array.
componentDidMount(){
console.log('Fetch');
fetch("https://horizons-json-cors.s3.amazonaws.com/products.json")
.then((resp) => (resp.json()))
.then((json) => {
var productUrlArr = [];
for (var i = 0; i < json.length; i++) {
productUrlArr.push(json[i].url);
}
console.log(productUrlArr);
}).catch((err) => {
console.log('error', err);
});
}
Hope it helps.
It simple. First get all the url first like you did. Then map and pass it into Promise.all.
fetch("https://horizons-json-cors.s3.amazonaws.com/products.json")
.then((resp) => (resp.json()))
.then((json) => {
Promise.all(json.map(product =>
fetch(product.url).then(resp => resp.text())
)).then(texts => {
// catch all the data
})
}).catch((err) => {
console.log('error', err);
});

get the all feeds data in single array in node.js

i have one doubt in the node js
i need to get the data from the rss feed
for that i install the rss-parser module in it
https://www.npmjs.com/package/rss-parser
let Parser = require('rss-parser');
let parser = new Parser();
(async () => {
let feed = await parser.parseURL('https://www.reddit.com/.rss');
console.log(feed.title);
feed.items.forEach(item => {
console.log(item.title + ':' + item.link)
});
})();
the code was like that
here they are using the async function
to get the data feed for one url
i have lot of urls
i need to loop it and get the feed details in single array
is there any posibility
please tell me is there any thing
i need to get the all feed url details in a single array
I tried as of now this
I tried this code
exports.getRssFeedLinks = () => {
// Setting URL and headers for request
// Return new promise
return new Promise((fulfill, reject) => {
// Do async job
let getSql = 'SELECT * FROM `news_feeds`';
//console.log(updateSql);
connection.query(getSql, (error, results, fileds) => {
if(error) {
reject(error);
}
else {
returnResult = JSON.stringify(results);
fulfill(returnResult);
}
});
})
}
exports.errHandler = function(err) {
console.log(err.message);
}
exports.getRssFeeds = (req, res) => {
let parser = new Parser();
let feedLink;
var dataPromise = this.getRssFeedLinks();
//console.log(dataPromise);
dataPromise.then(JSON.parse, this.errHandler)
.then(function(newFeeds) {
// Do one more async operation here
let feedsList = [];
if(newFeeds && newFeeds.length > 0) {
let feedLinks = [];
newFeeds.forEach(feed => {
feedLinks.push(feed.link);
});
(async () => {
let feeds = await Promise.all(feedLinks.map(parser.parseURL));
//feeds will have array of arrays, each array includes the response feed from each url
feeds = [].concat(...feeds) //if you want to flatten the array
feed.forEach(({item}) => {
console.log(item.title + ':' + item.link)
});
feeds.forEach(feed => {
console.log(feed.title);
feed.items.forEach(item => {
console.log(item.title + ':' + item.link)
});
})
})();
}
if(feedsList.length >0) {
res.send({
"success" : true,
"result" : feedsList
});
}
else {
res.send({
"success" : true,
"message" : "No Record ",
"result" : feedsList
});
}
}, this.errHandler);
}
Errors
(node:5700) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: Cannot read property
'options' of undefined
(node:5700) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
You can use Promise.all to send multiple request.
(async () => {
let feeds = await Promise.all(['https://www.reddit.com/.rss1', 'https://www.reddit.com/.rss2'].map(parser.parseURL));
//feeds will have array of arrays, each array includes the response feed from each url
feeds = [].concat(...feeds) //if you want to flatten the array
feed.forEach(({item}) => {
console.log(item.title + ':' + item.link)
});
//or use loop through each feed
feeds.forEach(feed => {
console.log(feed.title);
feed.items.forEach(item => {
console.log(item.title + ':' + item.link)
});
})
})();