Reputation: 21
I am fairly new to node.js and I'm still learning my way around coding in general.
The following things are what I'm trying to accomplish...
[*]Request data from api.
[*]Write the data into a new JSON file.
[*]Read the newly written file.
[*]Extract specific information.
This is what I have going for me so far
let request = require('request'),
fs = require('fs'),
DATA = require('./DATA.json'),
url = "https://dataThatIAmTryingToGet";
request(url, (error, response, body)=> {
if (!error && response.statusCode === 200) {
fs.writeFile("./DATA.json", (body))
} else {
console.log("Got an error: ", error, ", status code: ", response.statusCode)
}
});
if (fs.existsSync("./DATA.json")){
fs.readFile("./DATA.json", (err, data) => {
if (err) {
console.log("Whoopsiedaisy");
} else {
console.log("You did it nerd");
console.log(DATA.response.items.length);
}
})
};
With this code I accomplish the first two off my checklist...
[X]Request data from api.
[X]Write the data into a new JSON file.
[*]Read the newly written file.
[*]Extract specific information.
The console is printing You did it nerd
, but the error I am getting is that console.log(DATA.response.items.length);
is returning undefined
in the console. Im trying to see how many specific items fall under items
in the api. (Example of the api below). My issue is that I'm not sure if it's because the file is being read too fast, or if I'm trying to read the data incorrectly.
Here is an example of the api output...
{
"response": {
"success": 1,
"current_time": 1488743993,
"raw_usd_value": 0.1,
"usd_currency": "coins",
"usd_currency_index": 5002,
"items": {
"Item 1": {
"defindex": [
5002
],
"prices": {
"6": {
"Tradable": {
"Craftable": [
{
"value": 0.08,
"currency": "usd",
"difference": 0,
"last_update": 1488385886,
"value_high": 0.12
}
]
}
}
}
},
"Item 2": {
"defindex": [
5021
],
"prices": {
"6": {
"Tradable": {
"Craftable": [
{
"value": 14,
"currency": "usd",
"difference": 14.11,
"last_update": 1488385975,
"value_high": 14.22
}
]
}
}
}
}
}
}
}
Upvotes: 2
Views: 1621
Reputation: 73241
I would use a promise's to do such tasks. This will make the order of tasks very clear, and you get easily readable code without many nested callbacks. In below example I'm using bluebird for the promises, but you can implement the "promisification" for yourself if you insist. Below will do what you want (checking for fs.existsSync
is not needed, should the file not exist it will simply throw an error in fs.readFile
which you can handle in catch
.
Little sidenote: response.items.length
returns undefined because items
is an object in your case, which doesn't have a length
property. I suppose you've mixed that with an array.
const Promise = require('bluebird');
const request = Promise.promisifyAll(require('request'));
const fs = Promise.promisifyAll(require('fs'));
const url = 'http://localhost:3000';
request.getAsync(url)
.then(data => fs.writeFileAsync("output.json", data.body))
.then(() => fs.readFileAsync("output.json", "UTF-8"))
.then(data => console.log(JSON.parse(data).response))
.catch(err => console.log(err));
Here's a simple mock server that just returns the data you posted:
/* MOCK SERVER */
const http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify({
"response": {
"success": 1,
"current_time": 1488743993,
"raw_usd_value": 0.1,
"usd_currency": "coins",
"usd_currency_index": 5002,
"items": {
"Item 1": {
"defindex": [
5002
],
"prices": {
"6": {
"Tradable": {
"Craftable": [
{
"value": 0.08,
"currency": "usd",
"difference": 0,
"last_update": 1488385886,
"value_high": 0.12
}
]
}
}
}
},
"Item 2": {
"defindex": [
5021
],
"prices": {
"6": {
"Tradable": {
"Craftable": [
{
"value": 14,
"currency": "usd",
"difference": 14.11,
"last_update": 1488385975,
"value_high": 14.22
}
]
}
}
}
}
}
}
})
);
}).listen(3000);
/* END MOCK */
Upvotes: 1
Reputation: 3798
You are writing the file asynchronously. This means that it will call fs.writeFile
but then continue without waiting for it to finish. Because writing to the file system takes a [very small] amount of time, the program goes and calls the rest of the code while fs.writeFile
is still going.
To fix this, simply put the rest of your code in the callback of fs.writeFile
.
Hope that makes sense. See the fixed code below:
let request = require('request'),
fs = require('fs'),
DATA = require('./DATA.json'),
url = "https://dataThatIAmTryingToGet";
request(url, (error, response, body) => {
if (!error && response.statusCode === 200) {
fs.writeFile("./DATA.json", (body), function () {
if (fs.existsSync("./DATA.json")) {
fs.readFile("./DATA.json", (err, data) => {
if (err) {
console.log("Whoopsiedaisy");
} else {
console.log("You did it nerd");
console.log(DATA.response.items.length);
}
})
}
})
} else {
console.log("Got an error: ", error, ", status code: ", response.statusCode)
}
});
Upvotes: 0