If I call this function:
async function delete_get_note() {
let query = {
'command': 'delete_get_content',
'note_id': input_note_id.value
}
let response = await fetch(
'../api/api.php',
{
method: 'POST',
headers: {'Content-Type': 'application/json;charset=utf-8'},
body: JSON.stringify(query)
}
);
let result = await response.json();
log.innerHTML = result.log;
}
log displays the content of the json returned by my server. However, if I try to encapsulate the call to fetch in a function:
async function json_exchange(object) {
let response = await fetch(
'../api/api.php',
{
method: 'POST',
headers: {'Content-Type': 'application/json;charset=utf-8'},
body: JSON.stringify(object)
});
return await response.json;
}
And call:
async function delete_get_note() {
let query = {
'command': 'delete_get_content',
'note_id': input_note_id.value
}
let result = await json_exchange(query);
log.innerHTML = result.log;
}
Then log displays undefined.
What did I get wrong when I tried to put the call to fetch in a function ?
You forgot to add the parentheses to the json call:
return await response.json;
-->
return await response.json()
Tip: You can use TypeScript checking to easily detect such errors:
Related
I have the following two functions described in my Cloudflare worker code. However, when I run the code and these functions get called I get a TypeError: Cannot reconstruct a Request with a used body -
async function getApiV2Token(env: Env): Promise<string> {
let API_URL = await getApiUrl(env)
let API_CLIENT_ID = await getApiClientId(env)
let API_CLIENT_SECRET = await getApiClientSecret(env)
let apiUrl = `${API_URL}/auth`
let data = `client_id=${API_CLIENT_ID}&client_secret=${API_CLIENT_SECRET}`
let response, responseJSON
try {
response = await postData(apiUrl, data)
responseJSON = await response.json()
} catch (e) {
console.log(`Error: ${e}.`)
return ""
}
return responseJSON.auth_token
}
async function postData(url: string, data: string): Promise<Response> {
let request = new Request(url, {
method : 'POST',
body : data,
headers: {
'User-Agent': 'cloudflare-worker',
'Content-Type': 'application/x-www-form-urlencoded'
},
redirect : 'manual'
})
let cache = caches.default
let cachedResponse = await cache.match(request.url)
if (cachedResponse) {
return cachedResponse
}
console.log("checked cache")
let response = await fetch(request)
console.log("Requested new token")
let newResponseForExpiresIn = response.clone()
let newResponseForExpiresInJSON = await newResponseForExpiresIn.json()
let expires_in = newResponseForExpiresInJSON.expires_in
let newResponseForHeader = response.clone()
let newResponseToCache = new Response(newResponseForHeader.body, newResponseForHeader)
newResponseToCache.headers.set('Cache-Control', `max-age=${expires_in - API_TOKEN_GRACE_PERIOD}`)
cache.put(request.url, newResponseToCache)
return response
}
The line it fails at is let response = await fetch(request) (found this because "checked cache" is logged but not "Requested new token".
Here's what I've tried -
newRequest = request.clone() and then fetching that instead.
creating an identical request with new Request() and then fetching that.
same as above but using slice() to copy data
I also looked at Cloudflare Worker TypeError: One-time-use body but because I'm using the Cloudflare Worker Modules I don't have access to event. Any suggestions?
EDIT: I logged request.bodyUsed before the offending line and it logs false
I was able to fix this by constructing the request within fetch, not sure why.
const response = await fetch(url, {
method : 'POST',
body : data,
headers: {
'User-Agent': 'cloudflare-worker',
'Content-Type': 'application/x-www-form-urlencoded'
}
})
I've written an async function which is able to get a response from an API I've written in Python but I can't get the data into an array which I can then use to update my frontend application.
The code is as follows:
async function postData(URL) {
let rawResponse = await fetch(URL, {
method: "Post",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify(inputData),
});
const data = await rawResponse.json();
console.log(data);
return data;
}
let response1 = postData();
console.log(response1);
let response2 = postData()["returnedData"];
console.log(response2);
The code returns the array I want when I console.log the data variable within the function. However, it returns an array called 'Promise{pending}'* for response1 which contains the desired data but I am not able to manipulate it and returns 'undefined' for response2. What am I doing wrong?
Thanks in advance!
*pending even though the PromiseState is 'fulfilled'
PostData Function is a aync Function so returns a Promise so you must use await before calling it or .then
async function postData(URL) {
let rawResponse = await fetch(URL, {
method: "Post",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify(inputData),
});
const data = await rawResponse.json();
console.log(data);
return data;
}
// Method 1
const init = async () => {
let response1 = await postData();
console.log(response1);
let response2 = await postData()["returnedData"];
console.log(response2);
}
init();
// Method 2
(async () => {
let response1 = await postData();
console.log(response1);
let response2 = await postData()["returnedData"];
console.log(response2);
})()
When I submit my form, I am not returning any data, not even in my console. I am trying to return details from WHOIS regarding the URL that is searched, and am getting nothing back.
Can anyone provide any advice as to why this might be the case?
Here is my front end script tag, after my form:
document.getElementById('search').addEventListener('submit', function(e) { e.preventDefault(); getDetails(); })
async function getDetails(url = `http://localhost:3000/lookup/${url}`, data = {}) {
return new Promise(function (resolve, reject) {
fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'text/html'
},
body: JSON.stringify(data)
}).then(async response => {
if (response.ok) {
response.json().then(json => resolve(json))
console.log(data);
} else {
response.json().then(json => reject(json))
}
}).catch(async error => {
reject(error)
})
})
}
On my express backend I am using req.params.url if that helps provide any context at all...
My Status Code is 200, and all appears to be normal in the Headers tab...
You have a mix of promise and async syntax, which is confusing, let's translate it first by unpicking the promise and then into await (if you can use async then do, it's easer than Promise/then):
document.getElementById('search').addEventListener(
'submit',
function(e) {
e.preventDefault();
getDetails();
});
async function getDetails(url = `http://localhost:3000/lookup/${url}`, data = {})
{
// Fetch will throw an exception if it can't connect to the service
const response = await fetch(url, {
method: 'GET',
headers: { 'Content-Type': 'text/html' },
body: JSON.stringify(data)
});
if (response.ok)
return await response.json();
// We could connect but got an error back from the service
// There may not be a response body, so response.json() or .body() might crash
throw new Error(`Error from server ${response.status}: ${response.statusText}`;
// We don't need catch, as any exception in an await will cascade up anyway
}
This makes it much more readable, and it's apparent that getDetails doesn't make any changes itself, it just returns the JSON from the service. The fix needs to be in the event listener - it needs to do something with that result:
document.getElementById('search').addEventListener(
'submit',
async e => {
e.preventDefault();
const searchResult = await getDetails();
// Do something to show the results, populate #results
const resultsElement = document.getElementById('results');
resultsElement.innerText = JSON.stringify(searchResult);
});
You are mis-using async/await. Try this:
async function getDetails(url = `http://localhost:3000/lookup/${url}`, data = {}) {
const response = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'text/html'
},
body: JSON.stringify(data)
});
const json = await response.json();
if (response.ok) {
console.log(json);
return json;
} else {
throw new Error(json);
}
}
In essence await is a replacement for then (but you can only use it in functions marked with async).
I'm struggling to return the synchronous results of the method below.
I call the method from a different method:
var result = this.getVendor(id)
console.log(result)
Here is the fetch method:
methods: {
async getData(id) {
const response = await fetch(`${API_URL}api/${id}`, {
method: "GET",
headers: {
authorization: `Bearer ${localStorage.token}`
}
})
.then(res => res.json())
.then(data => {
return data;
});
await response;
}
}
How do I return the results response of the getData() function to show in the console?
Async functions Always return a promise.
You can use the await syntax to return it properly.
async getData(id) {
const response = await fetch(`${API_URL}api/${id}`, {
method: "GET",
headers: {
authorization: `Bearer ${localStorage.token}`
}
})
const data = await response.json()
return data
}
You can access the data out of that function anywhere you call it.
let data = null
object.getData(2)
.then(x => {
data = x
})
Also if you are going to use async await make sure to use try and catch to handle any errors that come up.
async getData(id) {
try {
const response = await fetch(`${API_URL}api/${id}`, {
method: "GET",
headers: {
authorization: `Bearer ${localStorage.token}`
}
})
const data = await response.json()
return data
}
} catch(err) {
console.error(err)
}
I'm trying to make a fetch call and it works but when I try to get the result from another function I always get undefined.
This is my code:
const fetch_output = async (data) => {
await fetch("execute_command", {
method: "POST",
credentials: "same-origin",
headers: {
"X-CSRFToken": getCookie("csrftoken"),
"Accept": "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify(data)
}).then(function(response) {
return response.json()
}).then(function(response) {
console.log(response)
//I get the correct response here
return response
}).catch(function(ex) {
console.log("Ha habido algĂșn error: ", ex)
})
}
const write_outputs = async () => {
for (const platform_id of platforms_ids) {
const data = {
platform_id:platform_id,
command:command
}
await fetch_output(data).then((resp)=>{
console.log(resp)
//I get undefined
})
}
}
write_outputs()
I've tried everything but I just don't know what am i doing wrong.
it is because an async function returns a promise that resolves to the returned value from the function
(async () => {})().then(value => console.log("value = ", value)); // undefined
(async () => {return 1})().then(value => console.log("value =" , value)); // 1
as you are not returning anything from fetch_output, it resolves to undefined
You should return from the fetch_output function instead of using await.
Also, because fetch is already a promise you can use a normal function instead of an async one
Because you call await fetch_output() you should not use .then() to retrieve its result. Drop the await.
Why? await replaces function().then().catch() with result = await function() in the way it handles a Promise or an async function. Use await or .then() but not both.