Passing a value from one request to another request in ReactJs - javascript

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,
// ...
}

Related

Having a problem properly getting information from canvas and sending information to discord through webhook with node-fetch

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

How to import external data fetch api into react componentDidMount method

I'm trying to consolidate some code in one of my react components because my componentDidMount method is getting a bit verbose. This gave me the idea to create an api that does all of my data fetching for the entire app.
I'm having an asynchronous issue I'm not sure how to resolve.
I created the separate api file (blurt.js):
exports.getBlurts = function() {
var blurtData = null;
fetch('/getblurts/false', {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
})
.then(res => res.json())
.then((data) => {
blurtData = data;
});
return blurtData;
}
and imported it to my (.jsx) component via
import blurtapi from '../api/blurt.js';
The problem is that when I call blurtapi.getBlurts() within componentDidMount(), the value comes back as null. However, if I write the data to the console like so:
.then((data) => {
console.log(data);
});
all is as it should be. So, the function is returning before the db operation completes, hence the null value. How would I reign in the asynchronous aspect in this case? I tried an async.series([]) and didn't get anywhere.
Thanks
So fetch returns a promise, which it is async , so any async code will run after sync code. so this is the reason you get null at first.
However by returning the async function , you are returning a promise.
Hence this code:
exports.getBlurts = async () => {
const data = await fetch('/getblurts/false', {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
});
const jsonData = await data.json();
return jsonData;
}
To retrieve any promise data, you need the then function,
so in your componentDidMount, you will do:
componentDidMoint() {
blurtapi.getBlurts()
.then(data => console.log(data)) // data from promise
}
Promises:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
async/await:
https://javascript.info/async-await
I hope this makes sense.
fetch call returns a promise. therefore in your function u do something like this
exports.getBlurts = function() {
var blurtData = null;
return fetch('/getblurts/false', {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
})
.then(res => res.json())
}
And do this in your componentDidMount
componentDidMount(){
blurtapi.getBlurts().then((data)=>{
this.setState({data})
}
}
In your example return blurtData; line will run synchronously, before the promise is resolved.
Modify getBlurts as:
exports.getBlurts = function() {
return fetch('/getblurts/false', {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
})
.then(res => res.json())
.then((data) => {
return data;
});
}
And in componentDidMount:
componentDidMount() {
getBlurts.then((data) => {
// data should have value here
});
}
exports.getBlurts = function() {
return fetch('/getblurts/false', {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
})
.then(res => res.json())
.then(res => return res)
async componentDidMount() {
const response = await blurtapi.getBlurts();
}
or
exports.getBlurts = function() {
return fetch('/getblurts/false', {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
})
.then(res => res.json())
componentDidMount() {
const data = blurtapi.getBlurts()
.then(data => {
// Do something or return it
return data;
});
}

making two fetch requests in one function with a delay in between

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

Fetching only JSON Object from response [duplicate]

I have a oauth set up. But when I want to get the access token with the fetch() function it just returns an object with things like _bodyInit, _bodyBlob and headers. So I just cannot get a JSON object. I'm on Android if that matters in any way.
Code:
componentDidMount() {
Linking.getInitialURL().then(url => {
if(url) {
console.log(url);
const queries = url.substring(16)
const dataurl = qs.parse(queries);
if(dataurl.state === 'ungessable15156145640!') {
console.log(dataurl.code);
console.log(dataurl.state);
return code = dataurl.code;
}
}
}).then((code) => {
fetch(`https://dribbble.com/oauth/token`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
'client_id': 'MY_ID',
'client_secret': 'MY_SECRET',
'code': code
})
})
.then((res) => {
var access_token = res;
console.log(access_token);
});
});
}
You almost got it right, you are missing one step though!
fetch doesn't return a json object, it returns a Response object, in order to get the json object, you have to use res.json()
fetch(`https://dribbble.com/oauth/token`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
'client_id': 'MY_ID',
'client_secret': 'MY_SECRET',
'code': code
})
})
.then((res) => {
return res.json();
})
.then((json) => {
console.log(json); // The json object is here
});
It's a good practice to add a catch just in case something goes wrong.
.then((json) => {
console.log(json); // The json object is here
});
.catch((err) => {
// Handle your error here.
})

No JSON object with fetch()

I have a oauth set up. But when I want to get the access token with the fetch() function it just returns an object with things like _bodyInit, _bodyBlob and headers. So I just cannot get a JSON object. I'm on Android if that matters in any way.
Code:
componentDidMount() {
Linking.getInitialURL().then(url => {
if(url) {
console.log(url);
const queries = url.substring(16)
const dataurl = qs.parse(queries);
if(dataurl.state === 'ungessable15156145640!') {
console.log(dataurl.code);
console.log(dataurl.state);
return code = dataurl.code;
}
}
}).then((code) => {
fetch(`https://dribbble.com/oauth/token`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
'client_id': 'MY_ID',
'client_secret': 'MY_SECRET',
'code': code
})
})
.then((res) => {
var access_token = res;
console.log(access_token);
});
});
}
You almost got it right, you are missing one step though!
fetch doesn't return a json object, it returns a Response object, in order to get the json object, you have to use res.json()
fetch(`https://dribbble.com/oauth/token`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
'client_id': 'MY_ID',
'client_secret': 'MY_SECRET',
'code': code
})
})
.then((res) => {
return res.json();
})
.then((json) => {
console.log(json); // The json object is here
});
It's a good practice to add a catch just in case something goes wrong.
.then((json) => {
console.log(json); // The json object is here
});
.catch((err) => {
// Handle your error here.
})

Categories