My flask app is not answering to fetch() with json [duplicate] - javascript

This question already has answers here:
Return JSON response from Flask view
(15 answers)
Closed 3 days ago.
This is my function in flask which is rolling 6 side dice:
#bp.route('/character', methods=('GET', 'POST'))
#login_required
def character():
throws = []
def roll_1d6():
return random.randint(1,6)
def roll_4d6(num_dice):
for i in range(num_dice):
throws.append(roll_1d6())
return json.dumps(throws)
return render_template('dd_roller/create_character.html', throws=throws)
I was also using make_response(json.dumps(throws)) and jsonify(throws)
And my javascript:
<script>
function getData() {
fetch('/character')`your text`
.then(response => response.json())
.then(throws => {
document.getElementById("get_data").innerHTML = "You rolled a " +throws;
console.log(throws);
})
}
</script>
<button onclick="getData()">ROLL</button>
<p id="get_data"></p>
Is giving me all the time error:
Uncaught (in promise) SyntaxError: Unexpected token '<', "<!doctype "... is not valid JSON
How can I make button which will fetch() value from my function in flask?

I don't know if it's right way to do it but it work for me that way:
I made new endpoint in init.py file.
#app.route('/attribute', methods=('GET', 'POST'))
def attribute():
throws = []
def roll_1d6():
return random.randint(1,6)
def roll_4d6(num_dice):
for i in range(num_dice):
throws.append(roll_1d6())
jsonify(throws)
return throws
roll_4d6(4)
return jsonify(throws)
And it work
enter image description here

Related

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
});

Can't store API data in js global variable [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Using async/await with a forEach loop
(33 answers)
Closed 1 year ago.
I am trying to build a simple crypto portfolio in nodejs by fetching prices from coingecko API. I set up a simple mongodb with all assets and I am parsing through the db and fetching each price. The fetch works as I can console.log the results however I cannot seem to be able to store the prices in a variable that I can call outside the fetch function. Thus, I cannot pass the prices to my ejs file. I am quite new to js (coming from python), and it seems that I am missing someting on how to handle api results, here is my code:
app.get('/dashboard', (req, res) => {
Holdings.find ((err, allHoldings) => {
if (err) {
res.type('html').status(500);
res.send('Error: ' + err);
}
else if (allHoldings.length == 0) {
res.type('html').status(200);
res.send('You have no holdings');
}
else {
var priceList = {};
allHoldings.forEach(async coin => {
coin = coin.asset;
const uri = 'https://api.coingecko.com/api/v3/simple/price?ids=' + coin + '&vs_currencies=usd&include_market_cap=false&include_24hr_vol=false&//include_24hr_change=false&//include_last_updated_at=false';
const fetch_price = await fetch(uri);
const json = await fetch_price.json()
const price = json[coin]['usd'];
priceList[coin] = price;
priceList.save;
console.log(priceList);
return priceList;
});
console.log(priceList);
res.render('dashboard', { holdings : allHoldings})
}
});
});
As you can see I set a priceList object before performing the API fetch and then I try to push the pair {coin : price} to that object. The first console.log works fine, however the second one only logs an empty object.
Any idea ?
Thanks

Can 't fecth content whit query.ID in nextJS

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

'Bad request' error on flask [duplicate]

When pressing a button i call a javascript function in my html file which takes two strings as parameters (from input fields). When the function is called i want to pass these parameters to my flask file and call another function there. How would i accomplish this?
The javascript:
<script>
function ToPython(FreeSearch,LimitContent)
{
alert(FreeSearch);
alert(LimitContent);
}
</script>
The flask function that i want to call:
#app.route('/list')
def alist(FreeSearch,LimitContent):
new = FreeSearch+LimitContent;
return render_template('list.html', title="Projects - " + page_name, new = new)
I want to do something like "filename.py".alist(FreeSearch,LimitContent) in the javascript but its not possible...
From JS code, call (using GET method) the URL to your flask route, passing parameters as query args:
/list?freesearch=value1&limit_content=value2
Then in your function definition:
#app.route('/list')
def alist():
freesearch = request.args.get('freesearch')
limitcontent = request.args.get('limit_content')
new = freesearch + limitcontent
return render_template('list.html', title="Projects - "+page_name, new=new)
Alternatively, you could use path variables:
/list/value1/value2
and
#app.route('/list/<freesearch>/<limit_content>')
def alist():
new = free_search + limit_content
return render_template('list.html', title="Projects - "+page_name, new=new)

Django - simplejson response

I'm using jQuery autocomplete plugin http://www.devbridge.com/projects/autocomplete/jquery/ to provide search suggestions in my web application where I want to send the response in json format.
Django views.py for sending the suggestions response:
def keywords_suggestions(request):
if request.is_ajax():
suggestions = []
q = request.POST.get('q')
try:
g = KeywordsModel.objects.filter(keyword__startswith=q).order_by('count')
except KeywordsModel.DoesNotExist:
return HttpResponse("")
else:
for i in range(0,len(g)):
global suggestions
suggestions.append(g[i].keyword)
to_json = {
"query": q,
"suggestions": suggestions
}
return HttpResponse(simplejson.dumps(to_json), mimetype='application/json')
Django models.py:
class KeywordsModel(models.Model):
keyword = models.CharField(max_length=40, blank=False)
count = models.IntegerField(max_length=20)
def __unicode__(self):
return self.keyword
jQuery code:
$("#add-keywords").keyup(function() {
$('#add-keywords').autocomplete({
serviceUrl:'/keywords_suggestions',
minChars:3,
maxHeight:220,
width:280,
zIndex: 9999,
params: { q: $('#add-keywords').val() },
onSelect: function(value, data){ $('#add-keywords').val(value); },
});
});
I'm getting this error when I type on the #add-keywords text box.
Request URL:http://127.0.0.1:8000/keywords_suggestions/?q=web&query=web
Request Method:GET
Status Code:500 INTERNAL SERVER ERROR
UPDATE
ValueError at /keywords_suggestions/
The view information.views.keywords_suggestions didn't return an HttpResponse object.
UPDATE-2
I'm having doubt in the suggestions variable, maybe global suggestions will have the problem. Am I doing it right?
Could anyone guide me to make it work?
UPDATE-3
<input type="text" id="add-keywords" name="add-keywords" title="e.g. Web developer, Javascript, Musician, Jazz" />
How to get the value of #add-keywords text box in the Django views.py. Does this work q = request.POST.get('add-keywords')?
Thanks!
the judgement request.is_ajax() returns False
The condition branches
try:
g = KeywordsModel.objects.filter(keyword__startswith=q).order_by('count')
except KeywordsModel.DoesNotExist:
return HttpResponse("")
else:
...
also could fail as ValueError if, for example, request.POST.get('q') results None
Plus, try '/keywords_suggestions/', note the suffix slash, instead of '/keywords_suggestions' in the serviceUrl:'/keywords_suggestions', line

Categories