so I have 2 endpoints, I'm making a "post" request to the first one and in the response I should get some kind of id that I use in the second request endpoint url. so I want to make a delay or something till I get the response from the first request.
req = () => {
fetch('url', {
method: 'POST',
headers: {
'Authorization': bearer,
'Content-Type': 'application/json',
},
body:
})
.then(response => response.json())
.then(json => {
})
fetch(`url with the id I get from the first request`, {
method: 'GET',
headers: {
'Authorization': bearer,
'Content-Type': 'application/json',
}
})
.then(response => response.json())
.then(json => {
})
}
There is no need for a delay per se. You can place your second request in the .then of the first request. This will ensure that your second request will run only once the first one has resolved. Another important note here, is that if you need a value of the first response in order to make the second request, you can only do that in the .then of the first request because otherwise the value you need to make the second request will be out of scope. Here is your code with the required modification.
req = () => {
fetch('url', {
method: 'POST',
headers: {
'Authorization': bearer,
'Content-Type': 'application/json',
},
body:
})
.then(response => response.json())
.then(json => {
fetch(`url with json.id or whatever`, {
method: 'GET',
headers: {
'Authorization': bearer,
'Content-Type': 'application/json',
}
})
.then(response => response.json())
.then(json => {
})
})
}
You can chain your second fetch request in your first request as:
req = () => {
fetch("url", {
method: "POST",
headers: {
Authorization: bearer,
"Content-Type": "application/json"
}
body:
})
.then(response => response.json())
.then(json => {
fetch("url with the id I get from the first request", {
method: "GET",
headers: {
Authorization: bearer,
"Content-Type": "application/json"
}
})
.then(response => response.json())
.then(json => {});
});
};
Or you can use async/await.
req = async () => {
const first = await ( await fetch( "url", {
method: "POST",
headers: {
Authorization: bearer,
"Content-Type": "application/json",
},
body:
} ) ).json();
const second = await ( await fetch( `http://some.url${ first.id }` ),
{
method: "GET",
headers: {
Authorization: bearer,
"Content-Type": "application/json",
},
} ).json();
// use the variable second as your last result here.
};
Related
I need help because I couldn't use a separate function to generate the token - it gives out a promise, not a value. I was told that a value can only be used inside a function.
For each request, I generate a new token in the first request and then pass that token into the second request.
I tried making a separate function to generate the token, but fetch returns a promise.
As a result, I made such a big function and it works.
Is there a way to make a separate function for the first request and pass the result to the second request?
The first token generation function is required frequently, while the second request is always different.
fetch('/api/token', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ 'id': '5' }),
})
.then(response => response.json())
.then(result => {
fetch('/api/reviews', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + result.token,
},
body: JSON.stringify({ 'limit': 10 }),
})
.then(response => response.json())
.then(result => {
this.setState({ data: result.data });
})
})
create a function that return promise
async function getToken() {
return await fetch('/api/token', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ 'id': '5' }),
})
.then(response => response.json())
.then(result => {
return Promise.resolve(result.token);
}).catch(error => {
return Promise.reject(error);
})
}
async function getReview() {
const token = await getToken().then(token => {
return token
}).catch(error => {
//handle error
});
fetch('/api/reviews', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token,
},
body: JSON.stringify({ 'limit': 10 }),
})
.then(response => response.json())
.then(result => {
this.setState({ data: result.data });
})
}
i did not test this code but you get the idea
i will test and update my answer asap
Yes you can with async / await. It will allow you to lift the lexical scope of the API response from inside the .then "callback hell" and into the parent function scope.
Your separate function which fetches the token will return a promise, but then the requesting function will wait for the promise to execute and resolve before continuing.
async function fetchToken() {
const response = await fetch('/api/token', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ 'id': '5' }),
})
return await response.json();
}
async function getReviews() {
const response = await fetch('/api/reviews', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + result.token,
},
body: JSON.stringify({ 'limit': 10 }),
})
const result = await response.json();
this.setState({ data: result.data });
}
Additionally, if the token call does not need to be made every time the reviews call is made, then you can memoize the value, and use that memoized value.
const tokenMemo = useMemo(async () => await getToken(), []);
async function getReviews() {
const response = await fetch('/api/reviews', {
// ...
'Authorization': 'Bearer ' + tokenMemo,
// ...
}
So I am trying to send data from canvas's api using a GET and use that information and send a POST from the same endpoint to discord using node fetch. I can receive data from canvas without issue and I console log to make sure I have to right data, but I can't seem to get any information to discord. I am using discords webhooks and I can't figure out where I am going wrong.
fetch(url + `courses/${course}/discussion_topics` , {
method: "GET",
headers : {
'Authorization' : 'Bearer <auth token>',
'Content-Type' : 'application/json'
}
})
.then(res => res.json())
.then(data => {
console.log(data[0].id);
console.log(data[0].title);
console.log(data[0].message);
}
)
.then(fetch("https://discord.com/api/webhooks/893327519103746149/<webhooktoken>", {
method: "post",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: {content: 'hello world'}
}))
.catch(err => console.log(err))
});```
As mentioned in the comment, just in case you have some typo or misunderstanding.
Also, you need to JSON.stringyify your body.
Please try the example below:
fetch(url + `courses/${course}/discussion_topics`, {
method: "GET",
headers: {
Authorization: "Bearer <auth token>",
"Content-Type": "application/json",
},
})
.then(res => res.json())
.then(data => {
console.log(data[0].id);
console.log(data[0].title);
console.log(data[0].message);
})
.then(() =>
fetch(
"https://discord.com/api/webhooks/893327519103746149/<webhooktoken>",
{
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
username: "Canvas-Bot",
content: "hello world",
}),
}
)
.then(res => res.json())
.then(data => {
console.log({ data });
})
)
.catch(err => console.log(err));
Another approach would be in async/await. I think it is cleaner.
(async function main() {
try {
const res1 = await fetch(url + `courses/${course}/discussion_topics`, {
method: "GET",
headers: {
Authorization: "Bearer <auth token>",
"Content-Type": "application/json",
},
});
const data1 = await res1.json();
console.log(data1);
const res2 = await fetch(
"https://discord.com/api/webhooks/893327519103746149/<webhooktoken>",
{
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
username: "Canvas-Bot",
content: "hello world",
}),
}
);
const data2 = await res2.json();
console.log(data2);
} catch (err) {
console.log(err);
}
})();
I am calling this function on button click.
I have added a header in my API still it shows an error.
let getData = () => {
console.log("getData function started");
const options = {
method: "GET",
headers: new Headers({ 'content-type': 'application/json' }),
mode: 'no-cors'
};
fetch("http://167.71.226.242/", options).then((response) => {
console.log("Inside 1st then");
return response.json();
}).then((data) => {
console.log("Inside 2nd then");
console.log(data);
});
}
var requestOptions = {
'content-type': 'application/json',
method: 'GET',
redirect: 'follow'
};
fetch("http://167.71.226.242", requestOptions)
.then(response => response.json())
.then(data => console.log(data));
This code work. you don't use new Header(...) in options!
Read more about fetch()
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#supplying_request_options
It's possible you'll just want to do this and also use the correct header name as yours is lowercase:
fetch('/', {
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
}).then(...);
It doesn't look like you need to use new Headers(); as well.
You may also not need mode: 'no-cors' but that's your call :)
Trying multiple fetch Promises to the same URL, but with a different body to each call. Currently I'm writing them all out. How would I go about writing this in a less verbose fashion?
Promise.all([
fetch("https://cors-anywhere.herokuapp.com/https://api.myurl.com/verify", {
body: `link=${productVariant1}&license_key=${licenseKey}`,
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
method: "POST"
}).then(do something),
fetch("https://cors-anywhere.herokuapp.com/https://api.myurl.com/verify", {
body: `link=${productVariant2}&license_key=${licenseKey}`,
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
method: "POST"
}).then(do something),
]).then(data => {
/* process response */
}
There's 5 Promises in total, with only the productVariant part of the call being different.
Sure you can do it with map:
Promise.all([productVariant1, productVariant2].map((productVariant, i) => {
return fetch("https://cors-anywhere.herokuapp.com/https://api.myurl.com/verify", {
body: `link=${productVariant}&license_key=${licenseKey}`,
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
method: "POST"
}).then(data => console.log(`Promise ${i} done`))
})
).then(data => {
console.log("all promises done")
})
You could create a function:
function Fetch(body) {
return fetch("https://cors-anywhere.herokuapp.com/https://api.myurl.com/verify", {
body,
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
method: "POST"
}).then(doSomething)
}
// And then
Promise.all([
Fetch(`link=${productVariant2}&license_key=${licenseKey}`),
Fetch(`link=${productVariant2}&license_key=${licenseKey}`)
]).then(responses => {
// do something with responses
})
Or if the only thing you're changing
I'm trying to check the status of a login via REST call and JWT token so that if that status is not ok then it'll return false, but this is what I'm getting.
export function login(data){
fetch('http://localhost:8000/token-auth/', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(data)
}).then(res => res.json())
.then(json =>
console.log(json.token) <= This prints correctly
)
}
I tried adding in a check in this function, but then I no longer get the the token printed out
export function login(data){
fetch('http://localhost:8000/token-auth/', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(data)
}).then(res => {
if(res.ok){
console.log(res.json()) <= This prints something about promise
console.log(res.json().token) <= this prints 'undefined'
}
}).then(json =>
console.log(json.token) <= This prints 'undefined'
)
}
Can you use a catch block instead? Like so:
export function login(data){
fetch('http://localhost:8000/token-auth/', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(data)
}).then(res => res.json())
.then(json =>
console.log(json.token)
).catch(error =>
console.log(error.response)
)
}