I need to call a bunch of APIs and map their response data to respective data sources. I am able to do so using separate fetch() calls to the APIs. However, I want use Promise.all() to load data from all the APIs before displaying them in the app. I am however unable to successfully do so. Following is the snippet:
componentDidMount() {
this.fetchAPIs(); //function to call APIs
this.loadFontAsync(); //function to load custom font
}
fetchAPIs = async () => {
console.log('Fetching APIs')
await Promise.all([
fetch('http://192.168.0.111:8080/endpoint1', {
method: 'post',
mode: 'cors',
headers: {
'Accept': 'application/json',
'Content-type': 'application/json'
},
body: JSON.stringify({
"customerNo": this.state.custId,
})
}),
fetch('http://192.168.0.111:8080/endpoint2', {
method: 'post',
mode: 'cors',
headers: {
'Accept': 'application/json',
'Content-type': 'application/json'
},
body: JSON.stringify({
"customerNo": this.state.custId,
})
}),
fetch('http://192.168.0.111:8080/endpoint3', {
method: 'get',
mode: 'cors',
headers: {
'Accept': 'application/json',
'Content-type': 'application/json'
}
}),
fetch('http://192.168.0.111:8080/endpoint4', {
method: 'post',
mode: 'cors',
headers: {
'Accept': 'application/json',
'Content-type': 'application/json'
}
,
body: JSON.stringify({
"customerNo": this.state.custId,
})
})
])
.then((response) => Promise.all(response.map(res => res.json())))
.then((response) => {
this.setState({
//mapping response to dataSources chronologically
dataSource3: response[0],
dataSource1: response[1],
dataSource2: response[2],
dataSource4: response[3],
isLoading: false // to check if APIs are loaded
})
})
.catch((error) => {
Alert.alert("Promise not fulfilled");
console.error(error);
});
}
When I check the logs in the server where the API is hosted, there is no hit to any of the endpoints on executing this code.
Could anyone suggest on what I am missing?
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,
// ...
}
I'm new to programming and I'm currently working on a small project.
I'm trying to implement some authorization using JWT.
I've watched a few videos online and found that most people have the "Bearer" + access token in their headers.
I've gone through a few posts and I found that I needed to add the authorization "Bearer" myself but I'm not quite sure how to get there.
Can I please get some help?
Here are some of my code
Login
if(response){
if(await bcrypt.compare(loginPW, response.password)){
const accessToken = jwt.sign({
email: response.email
},jwtSecret)
res.json({status: 'ok', accessToken: accessToken})
}else{
return res.json({status: 'error', error:'Invalid Credentials'})
}
}
Post request
const result = await fetch('/',{
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
loginEmail, loginPassword, reqType
})
}).then((res) => res.json());
just add Authorization header with your token to request
const result = await fetch('/',{
method: 'POST',
headers: {
'Content-Type': 'application/json'
'Authorization': `Bearer ${accessToken}`
},
body: JSON.stringify({
loginEmail, loginPassword, reqType
})
}).then((res) => res.json());
one possible way is ....on your Post requst result you can store the accessToken in localStorage
const result = await fetch('/',{
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
loginEmail, loginPassword, reqType
})
}).then((res) => res.json()).then(({accessToken})=>{
localStorage.setItem('accessToken', accessToken)
});
then retrieve it in all of your requests
const anotherRequst = await fetch('/anything',{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${localStorage.getItem('accessToken')}` // get it from localStorage
},
body: ... /// anything
}).then((res) => res.json());
that's the simplest way
... for more advanced techniques, try to use Axios
and you can simply set the default authorization header in all your requsts
axios.defaults.authorization = localStorage.getItem('accessToken')
then any request you make will have the accessToken in its header
Axios.post(....)
Axios.get(...)
....
You can add 'Authorization' headers within your request just like this
const result = await fetch('/',{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${accessToken}`
},
body: JSON.stringify({
loginEmail, loginPassword, reqType
})
}).then((res) => res.json());
Or if you're dealing with a big project and you have to send the token with every request then you can use Axios which allows you to add common headers with every request using only one line
axios.defaults.headers.common['Authorization'] = `Bearer ${accessToken}`;
Docs: https://www.npmjs.com/package/axios
I am trying to configure headers in a project with vue.js and axios to call a service that expects a json. My problem is that when I make my call with the POST method, axios puts to the request Content-Type header with x-www-urlencoded, but in my code, I put manually Content-Type header with application / json.
var loginObj = {
var1: payload.login,
var2: payload.password
}
const jsonLogin = JSON.stringify(loginObj)
const config = {
headers: {
'content-type': 'application/json',
'Accept': 'application/json'
}
}
axios({
url: 'url/example',
method: 'post',
data: jsonLogin,
config
})
.then(response => {
console.log(response);
})
.catch(error => {
console.log(error);
})
The Axios property to set header config should be headers: and you are setting with config:
try with:
axios({
url: 'url/example',
method: 'post',
data: jsonLogin,
headers: config.headers
})
or change your const config to:
const configHeaders = {
"content-type": "application/json",
"Accept": "application/json"
};
and use it with:
axios({
url: "url/example",
method: "post",
data: jsonLogin,
headers: configHeaders
});
I am trying to pass both formData and an apiKey in the body of a POST request, but it seems like its not working in my code below. What is the right syntax of doing that?
static login = (formData) => {
return fetch('/api/login', {
method: 'POST',
body: { formData,
JSON.stringify({
apiKey: 'xxxxxxxx'
}) },
headers: {
'Content-Type': 'application/json'
},
credentials: 'same-origin'
}).then(r => r.json())
}
I'm pretty sure that's just request-promise, but here
var login = (formData) => {
return fetch('/api/login', {
method: 'POST',
body: { formData:formData,
json:JSON.stringify({
apiKey: 'xxxxxxxx'
})
},
headers: {
'Content-Type': 'application/json'
},
credentials: 'same-origin'
}).then(r => r.json())
}
The body object needs to have keys assigned to the values
On the server, you can access them as body.formData and body.json
I am trying to upload file(image) from my react-native app to backend server. The RESTFUL backend server accepts file send via PUT method on a specific url. I am stuck on react-native trying to find the proper way to send file via PUT method.
I am trying to replicate behavior of
curl -X PUT -T "/path/to/file" "http://myputserver.com/puturl.tmp"
I found XMLHttpRequest method of doing this on a browser but won't work on react-native. Have anyone gone through this please help!!!
fetch('https://mywebsite.com/endpoint/', {
method: 'PUT',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
firstParam: 'yourValue',
secondParam: 'yourOtherValue',
}),
})
.then((response) => response.json())
.then((responseJson) => {
alert(responseJson)
})
.catch((error) => {
console.error(error)
})
reference
reference 2
Fetch
Use the fetch api, which is supported by React Native.
Below is an example of the official documentation.
Fetch supports PUT, according to the specs.
fetch('https://mywebsite.com/endpoint/', {
method: 'PUT',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
firstParam: 'yourValue',
secondParam: 'yourOtherValue',
})
})
You can use the PUT like the answer above. You might be missing the 'Content-Type': 'multipart/form-data;'.
const config = {
method: 'PUT',
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data;',
'Authorization': 'Bearer ' + 'SECRET_OAUTH2_TOKEN_IF_AUTH',
},
body: data,
}
Some more information in this blog post:
http://snowball.digital/Blog/Uploading-Images-in-React-Native