How to write api fetch results to file instead of console - javascript

How do you get the response from the fetch to write to a json file in the same directory, instead of the output to the console?
const sample = fetch('https://dummyapi.io/data/v1/user?limit=5&page=1', {
method: 'GET',
headers: {
'app-id': '63e798a1498c3c5fa3e2faeb',
},
})
.then(response => response.json())
.then(json => console.log(json));
I'm able to get the results to display in the console, per the code above, the fetch appears to be working, but I'd like to have the response write a new file(Newfile.json) in the same directory in json format. After I'm able to do this I'd like to do the same but write it to .csv (Newfile.csv)
I've tried the code below from another post, it creates the file but the contents of the file is just {}
const obj = fetch('https://dummyapi.io/data/v1/user?limit=5&page=1', {
method: 'GET',
headers: {
'app-id': 'xxxxxx',
},
})
const fs = require('fs');
fs.writeFile("test.json", JSON.stringify(obj), function(err) {
if(err) {
return console.log(err);
}
console.log("The file was saved!");
});

The file content is empty cause you are not writing anything to it.
You need to first extract the data from the response and then write it to your file being created, the code below should help you.
const sample = fetch('https://dummyapi.io/data/v1/user?limit=5&page=1', {
method: 'GET',
headers: {
'app-id': 'xxxxxx',
},
})
.then(response => response.json())
.then(data => {
const fs = require('fs');
fs.writeFile("test.json", JSON.stringify(data), function(err) {
if(err) {
return console.log(err);
}
console.log("The file was saved!");
});
})
.catch(error => {
console.error(error);
});
This should write the response to your test.json file but if you try to log the sample variable, it would return undefined because fetch is an async function and the writeFile function does not return anything, so the final then block in the chain of Promises does not have a value to resolve with.

Related

Refactor from fetch to await that can yield same result

So I moved over a non-reusable fetch request code snippet to my API:
let response = await fetch(visitURL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + userJWT
},
body: JSON.stringify(endingVisit)
});
if (response.ok) {
let {visitId, createdAt} = await response.json();
const viewVisitDto = new ViewVisitDto(`${visitId}${createdAt}${visitorId}${doctorId}${oldPatientId}`);
return viewVisitDto;
} else {
throw new Error("deactivated!")
}
I was able to get this far:
axios.post(visitURL, {
headers,
body: JSON.stringify(visit)
}).then((response) => {
console.log(response);
}).catch((error) => {
console.log(error);
})
But does not exactly give me the visitId and createdAt from the response and I cannot use a response.ok nor a response.json(). Essentially I need to pull out that visitId and createdAt that should be coming back in the response.
I also tried just using node-fetch library, but although in VS code it seems to accept it, TypeScript is not happy with it even when I do install #types/node-fetch and even when I create a type definition file for it, my API just doesn't like it.
Guessing what you are after is
// don't know axios, but if it returns a promise await it
const dto = await axios.post(visitURL, {
headers,
body: JSON.stringify(visit)
}).then((response) => {
// parse response
return {resonse.visitId, resonse.createdAt}
}).then(({visitId, createdAt}) => {
// form dto (where are other vals)?
return new ViewVisitDto(`${visitId}${createdAt}${visitorId}${doctorId}${oldPatientId}`);
}).catch((error) => {
console.log(error);
})
However - you don't mention where doctorId and oldPatientId come from... You try providing more info, including output of the console.log's and the surrounding code

What is wrong with my express parse setup?

Server
const express = require("express");
const app = express();
app.listen(4000, () => console.log("listening at 4000"));
app.use(express.static("public"));
app.use(express.json({limit: "1mb"}));
//POST method route
app.post("/clientApi", (req, res) => {
// res.send("POST request to the homepage")
console.log(req.body);
});
Client
function checkData() {
let summoner = playerName.value;
let fetchData = {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(summoner),
}
fetch("/clientApi", fetchData)
.then(response => response.json())
.then(data => {
console.log("Success: ", data);
});
}
Everything worked fine until I tried calling for Express.json but I don't see any syntax error.
The client side could send data to the server.
But it was too much data so I used "req.body" to try and get exactly what I wanted, but on the terminal its undefined. So that's when I decided to try using express.json which is where the error came up.
Error Message
Uncaught (in promise) SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
You forgot the {} after app.listen(4000, () => {console.log("listening at 4000")}); that should fix it
Actually you forgot to make proper JSON formate at client site:
function checkData() {
let summoner = playerName.value;
let sendData = {};
sendData.summoner = summoner;
let fetchData = {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(sendData),
}
fetch("/clientApi", fetchData)
.then(response => response.json())
.then(data => {
console.log("Success: ", data);
});
}
NOTE: Data you pass inside JSON.stringify() should a proper JSON Object. So that it can parse on the other side.
Try sending an object rather than just a string stringified such as
<script>
const playerName = {
value: "foobar"
};
function checkData() {
const summoner = { ...playerName };
const fetchData = {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(summoner),
}
fetch("/clientApi", fetchData)
.then(response => response.json())
.then(data => {
console.log("Success: ", data);
});
}
checkData();
</script>
Express won't be able to decode it otherwise.
Shouldn't fetch("/clientApi", fetchData) include http://localhost:4000/clientApi?

Javascript fetch API chain "then"

I'm kind of new to JS and can't figure out how to make the following work:
I'd like to run functions (for test reasons console) in the different stages of the fetch API. Like run console when fetch started because of click –> then when fetch received a response (text) -> then when the fetch response has been parsed -> and finally when the parsed response text has replaced the HTML of an existing DOM-element.
var doFetch = (url) => {
fetch(url, {
method: "GET",
headers: new Headers({
'X-Requested-With': 'fetch'
})
}){
console.log("fetch request started because of click on element");
}
.then(response => response.text();
console.log("fetch request has received the response text");
)
.then(response => {
let content = new DOMParser().parseFromString(text, "text/html");
console.log("the received request response text was DOMparsed");
})
.then(response => {
let main = content.querySelector('main').innerHTML;
console.log("the parsed response content replaced current HTML");
}
};
Any tips on how to correct the code would be gladly welcomed!
each then block will execute if previous then block return.
Your first console.log statement should be at the start of the doFetch function. It cannot be written where it is currently written in your code.
You should also chain a catch block at the end to catch any errors that might occur in the promise chain.
As a side note, you should use const or let keywords to declare variables instead of var.
const doFetch = (url) => {
console.log("fetch request started because of click on element");
fetch(url, {
method: "GET",
headers: 'X-Requested-With': 'fetch'
})
.then(response => {
console.log("fetch request has received the response text");
return response.text();
})
.then(response => {
console.log("the received request response text was DOMparsed");
return new DOMParser().parseFromString(text, "text/html");
})
.then(response => {
let main = content.querySelector('main').innerHTML;
console.log("the parsed response content replaced current HTML");
})
.catch(error => console.log(error));
};
In order to do chaining you need to return from each .then block. Aslo your first console.log() post the fetch function had incorrect syntax
var doFetch = (url) => {
fetch(url, {
method: "GET",
headers: 'X-Requested-With': 'fetch'
})
.then(response => {
console.log("fetch request has received the response text");
return response.text();
})
.then(response => {
let content = new DOMParser().parseFromString(text, "text/html");
console.log("the received request response text was DOMparsed");
return content
})
.then(content => {
let main = content.querySelector('main').innerHTML;
console.log("the parsed response content replaced current HTML");
});
console.log("fetch request started because of click on element"); // This will be executed first
};

Can i post text data using fetch in react

I'm using react js and I want to post text and return a text.
Can anyone help me in posting text and receiving text? I have used
content type text/plain but that didn't help.
Is there any way to do?
const options = {
method: "POST",
headers: {
"Content-Type": "text/plain"
},
body: this.state.url
}
fetch("http://localhost:3000/messages", options)
.then(response => response)
.then(data => {
console.log(data)
this.setState({
code: data
});
});
This is what I have tried to get the text value from api
I am getting an error as
Uncaught promise typeError failed to fetch
fetch returns a "promise" for a Response object which has promise creators for json, text, etc. depending on the content type. So the code should be changed to.
Also consider adding a catch block for the promise in case of errors and check the console output error (if any ).
const options = {
method: "POST",
headers: {
"Content-Type": "text/plain"
},
body: this.state.url
}
fetch("http://localhost:3000/messages", options)
.then(response => response.json()) // or response.text()
.then(data => {
console.log(data)
this.setState({
code: data
});
})
.catch(err => { console.log('error while fetching', err) });

How to get Readable error response from JavaScript Fetch API?

I am working on Reactjs redux on front-end and Rails API as a back-end.
So now I call API with Fetch API method but the problem is I cannot get readable error message like what I got inside the network tabs
this is my function
export function create_user(user,userInfoParams={}) {
return function (dispatch) {
dispatch(update_user(user));
return fetch(deafaultUrl + '/v1/users/',
{
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
method: "POST",
body: JSON.stringify(userInfoParams)
})
.then(function(response) {
console.log(response);
console.log(response.body);
console.log(response.message);
console.log(response.errors);
console.log(response.json());
dispatch(update_errors(response));
if (response.status >= 400) {
throw new Error("Bad response from server");
}
})
.then(function(json){
console.log("succeed json re");
// We can dispatch many times!
// Here, we update the app state with the results of the API call.
dispatch(update_user(json));
});
}
}
But when errors came I cannot figure out how to get readable response message like I got when I check on my browser network tabs
So this is what I got from the network tabs when I got errors.
My console
This is my rails code
def create
user = User.new(user_params)
if user.save
#UserMailer.account_activation(user).deliver_now
render json: user, status: 201
else
render json: { errors: user.errors }, status: 422
end
end
But I cannot find out how can I get that inside my function
Since the text is hidden inside promise within response object, it needs to be handled like a promise to see it.
fetch(bla)
.then(res => {
if(!res.ok) {
return res.text().then(text => { throw new Error(text) })
}
else {
return res.json();
}
})
.catch(err => {
console.log('caught it!',err);
});
Similar to your answer, but with a bit more explanation... I first check if the response is ok, and then generate the error from the response.text() only for the cases that we have a successful response. Thus, network errors (which are not ok) would still generate their own error without being converted to text. Then those errors are caught in the downstream catch.
Here is my solution - I pulled the core fetch function into a wrapper function:
const fetchJSON = (...args) => {
return fetch(...args)
.then(res => {
if(res.ok) {
return res.json()
}
return res.text().then(text => {throw new Error(text)})
})
}
Then when I use it, I define how to handle my response and errors as needed at that time:
fetchJSON(url, options)
.then((json) => {
// do things with the response, like setting state:
this.setState({ something: json })
})
.catch(error => {
// do things with the error, like logging them:
console.error(error)
})
even though this is a bit old question I'm going to chime in.
In the comments above there was this answer:
const fetchJSON = (...args) => {
return fetch(...args)
.then(res => {
if(res.ok) {
return res.json()
}
return res.text().then(text => {throw new Error(text)})
})
}
Sure, you can use it, but there is one important thing to bare in mind. If you return json from the rest api looking as {error: 'Something went wrong'}, the code return res.text().then(text => {throw new Error(text)}) displayed above will certainly work, but the res.text() actually returns the string. Yeah, you guessed it! Not only will the string contain the value but also the key merged together! This leaves you with nothing but to separate it somehow. Yuck!
Therefore, I propose a different solution.
fetch(`backend.com/login`, {
method: 'POST',
body: JSON.stringify({ email, password })
})
.then(response => {
if (response.ok) return response.json();
return response.json().then(response => {throw new Error(response.error)})
})
.then(response => { ...someAdditional code })
.catch(error => reject(error.message))
So let's break the code, the first then in particular.
.then(response => {
if (response.ok) return response.json();
return response.json().then(response => {throw new Error(response.error)})
})
If the response is okay (i.e. the server returns 2xx response), it returns another promise response.json() which is processed subsequently in the next then block.
Otherwise, I will AGAIN invoke response.json() method, but will also provide it with its own then block of code. There I will throw a new error. In this case, the response in the brackets throw new Error(response.error) is a standard javascript object and therefore I'll take the error from it.
As you can see, there is also the catch block of code at the very end, where you process the newly thrown error. (error.message <-- the error is an object consisting of many fields such as name or message. I am not using name in this particular instance. You are bound to have this knowledge anyway)
Tadaaa! Hope it helps!
I've been looking around this problem and has come across this post so thought that my answer would benefit someone in the future.
Have a lovely day!
Marek
If you came to this question while trying to find the issue because response.json() throws "Unexpected token at position..." and you can't find the issue with the JSON, then you can try this, basically getting the text and then parsing it
fetch(URL)
.then(async (response) => {
if (!response.ok) {
const text = await response.text()
throw new Error(text)
}
// Here first we convert the body to text
const text = await response.text()
// You can add a console.log(text), to see the response
// Return the JSON
return JSON.parse(text)
})
.catch((error) => console.log('Error:', error))
.then((response) => console.log(response))
I think you need to do something like this
export function create_user(user,userInfoParams={}) {
return function (dispatch) {
dispatch(update_user(user));
return fetch(deafaultUrl + '/v1/users/',
{
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
method: "POST",
body: JSON.stringify(userInfoParams)
})
.then(function(response) {
console.log(response);
console.log(response.body);
console.log(response.message);
console.log(response.errors);
console.log(response.json());
return response.json();
})
.then(function(object){
if (object.errors) {
dispatch(update_errors(response));
throw new Error(object.errors);
} else {
console.log("succeed json re");
dispatch(update_user(json));
}
})
.catch(function(error){
this.setState({ error })
})
}
}
You can access the error message with this way:
return fetch(deafaultUrl + '/v1/users/',
{
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
method: "POST",
body: JSON.stringify(userInfoParams)
})
.then(function(response) {
console.log(response);
console.log(response.body);
console.log(response.message);
console.log(response.errors);
console.log(response.json());
dispatch(update_errors(response));
if (response.status >= 400) {
throw new Error("Bad response from server");
}
})
.then(function(json){
console.log("succeed json re");
// We can dispatch many times!
// Here, we update the app state with the results of the API call.
dispatch(update_user(json));
})
// here's the way to access the error message
.catch(function(error) {
console.log(error.response.data.message)
})
;
The best choice is not to catch the error in the fetch because this will be useless:
Just in your api put a response with not code error
static GetInvoicesAllData = async (req,res) =>
{
try{
let pool = await new Connection().GetConnection()
let invoiceRepository = new InvoiceRepository(pool);
let result = await invoiceRepository.GetInvoicesAllData();
res.json(result.recordset);
}catch(error){
res.send(error);
}
}
Then you just catch the error like this to show the message in front end.
fetch(process.env.REACT_APP_NodeAPI+'/Invoices/AllData')
.then(respuesta=>respuesta.json())
.then((datosRespuesta)=>{
if(datosRespuesta.originalError== undefined)
{
this.setState({datosCargados:true, facturas:datosRespuesta})
}
else{ alert("Error: " + datosRespuesta.originalError.info.message ) }
})
With this you will get what you want.
You variables coming back are not in response.body or response.message.
You need to check for the errors attribute on the response object.
if(response.errors) {
console.error(response.errors)
}
Check here https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
You should actually be returning an error response code from the server and use the .catch() function of the fetch API
First you need to call json method on your response.
An example:
fetch(`${API_URL}`, {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(userInfoParams)
})
.then((response) => response.json())
.then((response) => console.log(response))
.catch((err) => {
console.log("error", err)
});
Let me know the console log if it didn't work for you.

Categories