Can 't fecth content whit query.ID in nextJS - javascript

I 'm traying to find out what I'm doing wrong in this code but y can't resolve it.
I need to use my query.id inside getInitialPops to fecth some contents. The fetch works, but in my catch i recives this error:
FetchError: invalid json response body at https://url/resume-true.json reason: Unexpected token < in JSON at position 0
The original endpoint its:
https://url/resume-${query.id}.json
and when I console.log the query.id returns, first
slug-5 (this is the rigth one)
and second:
true (I dont'know were this came from)
This is my getInitialProps
channelRouter.getInitialProps = async ({ query }) => {
console.log("query**", query.id);
try {
const res = await fetch(
`https://url/resume-${query.id}.json`
);
let data = await res.json();
return { data };
} catch (e) {
console.log(`${e}`);
}
};
Any idea?
Thanks!!

I have seen this error many times before.
FetchError: invalid json response body at https://url/resume-true.json reason: Unexpected token < in JSON at position 0
This means that your endpoint is returning HTML instead of JSON (hence the start with <)
Check your endpoint, it's not valid json, could be a 404 or 500 status in html

Related

Using Lambda with Nodejs Count Some queries in Dynamo DB

After using the below to pull data from Dynamo db sucessfully
async function pullone(sessionid) {
const params = {
TableName: dynamodbTableName,
Key: {
'sessionid': sessionid
}
};
return await dynamodb.get(params).promise().then((response) => {
return response.Item
}, (error) => {
console.error('Do your custom error handling here. I am just gonna log it: ', error);
});
}
Instead of 'return response.Item' i just want to return the count instead.
I tried doing count(pullone(sessionid)) but not sure if that is even a valid method. Please assist
Not sure if I understood your question, but:
Since you're requesting data associated with a primary key, you'll get either 0 or 1 element in Item.
So, if you aim to know if "you've found something or not", you can use Number(response.Item != null) and you'll get 1 in case of "something" and 0 in case of "nothing".
If, instead, your data contains a "count" attribute, then (await pullone(sessionId)).count should work.
Otherwise, you have to query your DB (but you'll get Items (plural) in your response) and use the length() function of the Items array you'll get in the response.

`JSON.parse(await response.json())` throws SyntaxError: unexpected character at line 1 column 2

I want to bring back the age property from the JSON created by the API but it throws this error:
SyntaxError: JSON.parse: unexpected character at line 1 column 2 of the JSON data
The console.log(await response.json()) gives me all my JSON data, but when I comment it out and put the last code line, this error occurs.
I was told to try one of these:
response.json()["age"]
response.json()[age]
response.json().age
let json = JSON.parse(response);
console.log(json["age"]) was close, but not successful.
let table = base.getTable("test");
let view = table.getView("Donnée brut");
let age;
let query = await view.selectRecordsAsync({
sorts: [
// sort by "Prénom" in ascending order...
{
field: "Prénom"
}
]
});
// print ID & "Prénom" from each record:
for (let record of query.records) {
let name = (record.getCellValueAsString('Prénom'));
var response = await fetch('https://api.agify.io/?name=' + name);
/* console.log(await response.json()); */
let json = JSON.parse(await response.json());
console.log(json["age"]);
}
Response.prototype.json already parses the JSON.
You’re correctly awaiting this promise: await response.json().
When logging, this already logs the parsed data you need: console.log(await response.json());.
When you try JSON.parse(await response.json()), you’re coercing the object back into a string, which results in "[object Object]", which is invalid JSON, hence the error message.
Remove this JSON.parse call.
If you need the age property of the parsed JSON, use console.log((await response.json()).age);.
Remember that .json returns a Promise, not the parsed object; that’s why response.json().age and the like won’t work.
You need to await before reading the property.
Alternatively, put the parsed result in a variable first:
// …
const result = await response.json();
console.log(result.age);
// …

Unexpected end of JSON input when using Promise.all() and put method in fetch

I encountered a problem using Javascript, when I try to get mail content from an API and update its read status concurrently. The error message in the console is:
SyntaxError: Unexpected end of JSON input
at inbox.js:98
The error promise in the log is as below.
1: Promise
[[Prototype]]: Promise
[[PromiseState]]: "rejected"
[[PromiseResult]]: SyntaxError: Unexpected end of JSON input at http://127.0.0.1:8000/static/mail/inbox.js:98:30
message: "Unexpected end of JSON input"
stack: "SyntaxError: Unexpected end of JSON input\n at http://127.0.0.1:8000/static/mail/inbox.js:98:30"
The code in line #98 is:
let res2 = response[1].json();
The full js code is as below. I have checked promises called res1 and res2. It seems that the problem lies in res2 since its return is rejected. I tried different ways to resolve it, but failed. I also don't understand why it is not caught by the catch function. Thank you in advance.
Though it returns SyntaxError every time. Both fetch functions have worked already...
async function show_single_mail(email_id){
// Show content of selected email
document.querySelector('#mails_table').style.display = 'none';
const email_div = document.createElement('div');
document.querySelector('#emails-view').append(email_div);
// Obtain email content and update its read status concurrently
const option2 = {
method: 'PUT',
body: JSON.stringify({read: true})}
Promise.all([fetch(`/emails/${email_id}`), fetch(`/emails/${email_id}`, option2)])
.then(response => {
let res1 = response[0].json();
let res2 = response[1].json();
console.log([res1, res2]);
return Promise.all([res1, res2])
})
.then(results => {
result = results[0];
email_div.innerHTML =
`<h3>Subject: ${result.subject}</h3><br>` +
`<p>Sender: ${result.sender}</p><br>`+
`<p>Receiver: ${result.recipients}</p><br>`+
`<p>Time: ${result.timestamp}</p><br>`+
`<p>Content: ${result.body}</p>`;
})
.catch(err => console.log(err))
}
You are doing two parallel requests with
Promise.all([fetch(...), fetch(...)])
which is fine. But when you handle your results, you are not checking, whether the requests were sucessfull or not, and fetch doesn't reject on 4xx status codes. Furthermore, your server obviously does not return JSON for an unsuccessful request but only text. It may even be, that the second request succeeds, but doesn't have a valid json body. Nobody knows what your API really does.
When you now do
.then(responses => {
responses[0].json(); //this response has a valid json body
responses[1].json(); //this one doesn't
})
the body of response[1] can't be parsed as json (which responses[1].json() tries to do). And thus, an error is thrown. So you have to check first, if your requests were successful/returned json before you can read their body
.then(responses => {
let s = responses.filter(x => x.ok); //status == 2xx
let f = responses.filter(x => !x.ok); //status != 2xx
//do something with failed requests and
//only read the body for successful responses
//return Promise.all(s.map(x => x.json());
//or try to read json for successful and text for unsuccessful responsees
//return Promise.all(responses.map(r => r.ok ? r.json() : r.text()));
//or try to check the contenttype of the responses (if the server correctly sets them
//return Promise.all(responses.map(r => r.headers.get("content-type").includes("application/json")
// ? res.json()
// : res.text()
// ));
})
.then(responses => {
//display them
});

Check if endpoint is working and if is not, get another URL with axios

I'm trying to learn about API consume with pokeapi and axios, and it seems like they are having problems with some end points, sometimes they are returning a 404 error. I want to use that error as to practice
I have the following code:
const pokemonDataList = []
for(i = 1; i ≤ quantity) {
const url = `https://pokeapi.co/api/v2/pokemon/${i}/`
pokemonDataList.push(await axios.get(url))
}
When I run that, everything works until a dead endpoint is accessed, then my local serve stop running and return a unhandled error message.
What I want to do is when the
await axios.get(url)
gets an error, like 404 or 500, I want to be able to fetch from another end point, and then go back for my initial looping, so something like this:
const pokemonDataList = []
for(i = 1; i ≤ quantity) {
const url = `https://pokeapi.co/api/v2/pokemon/${i}/`
if(axios.get(url) === success) {
pokemonDataList.push(await axios.get(url))
} else {
pokemonDataList.push(await axios.get(anotherUrl))
}
}
Is there a way to do something like that?
If an error occurs during an axios call you can use try/catch to handle the error that occurred:
for(i = 1; i ≤ quantity) {
const url = `https://pokeapi.co/api/v2/pokemon/${i}/`
try{
pokemonDataList.push(await axios.get(url))
}
catch (error) {
console.log(`Error occured on main endpoint ${url}: ${error.message}`);
console.log(`Fetching data form: ${anotherUrl}`);
pokemonDataList.push(await axios.get(anotherUrl));
}
}
Use the promises to handle the error, like so:
await axios.get(url).then((response) => {
console.log(response);
// Do something on success
}).catch((error) => {
console.error(error);
// Do something on error...
});

How can i handle multiple response in single route?

I Try to post an order. I get product's details as array of object(in that array I get product id and quantity). I'm using map function to iterate. Using id I here find all details of the product. Then I am doing before placing an order i am checking stock value and update it. When i try to send more than one object i am getting anUnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client at ServerResponse.setHeader (_http_outgoing.js:485:11)How can i solve this warning.And Also another is is stock condition is not working. eg:`If stock is 0 then it should give res.(404) intstead i'm getting 200 ok status
//2.Create a Order
router.post('/orders', (req,res) => {
//products is a array of object we get from frontend
const { products,name,mobile,pincode,address,district,email } = req.body;
if(!products || !name || !mobile || !pincode || !address || !district || !email) return res.sendStatus(409).json({message:'Fields cannot be empty'});
//Using map method to itreate each object in array
products.map( async product => {
try {
const orderedItem = await Product.findById(product.id);
const currentOrder = new Order({
productId:orderedItem.productId,
quantity: product.quantity,
orderId: orderedItem.orderId,
name,
mobile,
pincode,
address,
district,
email
});
//Stock updating
if(orderedItem.stock <= 0){
console.log('stock less or equal to is checking...');
return res.sendStatus(404).json({message:'oops! Product Out of Stock'});
}
if(currentOrder.quantity > orderedItem.stock){
console.log('remove product condition is checking')
return res.status(404).json({message:orderedItem.name+'Please remove the product'});
} //return res.sendStatus(404)//.json({message:'Quantity you choose is not available please try using less quantity'});
orderedItem.stock = orderedItem.stock-currentOrder.quantity;
await orderedItem.save();
await currentOrder.save();
// await sendEmail(orderedItem,currentOrder);
} catch (error) {
return res.sendStatus(500).json({message:error});
}
});
res.json({
message : 'Order placed!'
});
});
There are a couple of things wrong about your code.
You are using async-await inside a arr.map() function, which will not block the main thread and your res.json({message : 'Order placed!'}) will get called before your array elements are processed. Use a 'for' loop with await to block your main thread.
Solution- https://pouchdb.com/2015/03/05/taming-the-async-beast-with-es7.html
2.You are sending multiple responses to the client for a single request which is not allowed and therefore you are getting the error Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client at ServerResponse.setHeader (_http_outgoing.js:485:11). Change your code in such a way that it only sends one response for the incoming request.
Solution- https://stackoverflow.com/a/48123354/8393975

Categories