I have an angular 2app with a class and a method, the method executes a web api call and then sets some items on local storage, the problem is that because its ASYNC then on the next line I dont have the local storage values yet because the web api hasnt returned any info at that point.
How can I make sure that the web api has been succesfully returned before the localstorage.getitem line.
Code reduced for brevity.
Service
login(email) {
let params: URLSearchParams = new URLSearchParams();
params.set('email', email);
//Header
let headers = new Headers({
'Content-Type': AppSettings.ContentType,
'Authorization': AppSettings.Authorization + localStorage.getItem("AccessToken"),
'X-Developer-Id': AppSettings.XDeveloperId,
'X-Api-Key': AppSettings.XApiKey
});
var RequestOptions: RequestOptionsArgs = {
url: AppSettings.UrlLoginPatient,
method: 'GET',
search: params,
headers: headers,
body: null
};
this.http.get(AppSettings.UrlLoginPatient, RequestOptions)
.map(res => res.json())
.subscribe(
data => { this.saveData(data, email); },
err => this.Error(err)
);
}
saveData(data, email) {
localStorage.setItem('patientId', data.data.patientId);
localStorage.setItem('emailLogin', email);
}
Error(err) {
console.log('error: ' + err);
}
Component
LoginApp() {
this.login.login('a#com.com');
if (localStorage.getItem("patientId") != null) {
this.navCtrl.push(AttentionTypePage);
} else {
let alert = this.alertCtrl.create({
subTitle: 'El correo electrónico no ha sido encontrado.',
buttons: ['Intentar nuevamente']
});
alert.present();
}
}
To ensure that you have the right informations, you shouldn't subscribe in your service but in your component :
Service
login(email) {
//do stuff with headers, and request options
return this.http.get(AppSettings.UrlLoginPatient, RequestOptions)
.map(res => res.json())
.do(data => this.saveData(data, email));
}
Component
LoginApp() {
this.login.login('a#com.com').do(data => {
if (localStorage.getItem("patientId") != null) {
this.navCtrl.push(AttentionTypePage);
} else {
let alert = this.alertCtrl.create({
subTitle: 'El correo electrónico no ha sido encontrado.',
buttons: ['Intentar nuevamente']
});
alert.present();
}
}).subscribe();
}
Related
const loadLibrary = useCallback(async () => {
launchImageLibrary(
{
mediaType: 'photo',
},
response => {
if (response?.errorCode) {
console.log('LaunchImageLibrary Error: ', response.errorMessage);
} else {
console.log('response=', response.assets[0]);
const formData = new FormData();
formData.append('image', {
name: response.assets[0].fileName, // require, file name
uri: response.assets[0].uri, // require, file absoluete path
type: response.assets[0].type, // options, if none, will get mimetype from `filepath` extension
});
console.log('formData=', formData);
axios
.post('/users', formData)
.then(function (response) {
console.log(response.data);
})
.catch(function (error) {
console.log(error);
});
// );
}
},
);
}, [userInfo]);
spring code ---
#PostMapping(value="/api/v1/users")
public String createUser(
#RequestParam("image") MultipartFile image) {
System.out.println(image);
return "";
}
-error--
org.springframework.web.multipart.MultipartException: Current request is not a multipart request
how to deal with?
Previously, this code worked well.
try this and let me know
const formData = new FormData();
formdata.append("image", {type: 'image/jpg', uri:response.assets[0], name:response.assets[0]});
console.log('formData=', formData);
axios
.post('/users', formData)
.then(function (response) {
console.log(response.data);
})
.catch(function (error) {
console.log(error);
});
// );
}
},
);
I am trying to build a generic function for my endpoints, using Axios and React. Generic because I have always the same header and I do not want to repeat a lot of code for each of my components.
To do that, I built this function (sorry, a lot of comments that I will remove after of course) :
export const getRequest = ( endpoint ) => axios
.get( env._URL_SERVER_ + endpoint, { headers: getHeaders() } )
.then((res) => {
// Success
console.log(res);
return {error: false, response: res.data};
})
.catch((error) => {
// Error
if (error.response) {
/*
* The request was made and the server responded with a
* status code that falls out of the range of 2xx
*/
console.log(error.response.data);
console.log(error.response.status);
return {error: true, status: error.response.status, data: error.response.data};
} else if (error.request) {
/*
* The request was made but no response was received, `error.request`
* is an instance of XMLHttpRequest in the browser and an instance
* of http.ClientRequest in Node.js
*/
console.log(error.request);
return {error: true, data: error.request };
} else {
// Something happened in setting up the request and triggered an Error
console.log('Error', error.message);
return {error: true, data: error.message}
}
});
Ant then in my components I do that :
getSchools = () => {
this.setState({
loadingSchools: true
}, () => {
getRequest(`/schools?name=${this.state.filterByName}&city=${this.state.filterByCity}&school_type_id=${this.state.filterBySchoolTypeId}&page=${this.state.selectedPage}`)
.then((response) => {
// there is an error
if (!response.error) {
this.setState({
schools: response.response.data,
meta: response.response.meta,
links: response.response.links
})
} else {
this.setState({
error: true,
errorMessage: response.data,
})
}
})
.then(() => {
this.setState({loadingSchools : false});
})
})
}
It works fine. I tested it in several situation (all is OK - 200, not found - 404, no response). But is it a good practice ? I feel that there is a lot of codes in the parent component. Maybe I complicate my life?
Here is how I've done it:
var URL_BACKEND = "http://localhost:5000/";
// Create Function to handle requests from the backend
callToBackend = async (ENDPOINT, METHOD) => {
const options = {
url: `${URL_BACKEND}${ENDPOINT}`,
method: METHOD,
headers: {
Accept: "application/json",
"Content-Type": "application/json;charset=UTF-8",
},
};
const response = await axios(options);
return response.data;
}
// Then you make a call with the exact endpoint and method:
const response = await this.callToBackend('createSetupIntent', 'POST');
console.log(JSON.stringify(response));
create one common file for base URL let's say api.js
// api.js file code
export const apiUrl = axios.create({
baseURL: 'http://localhost:5000',
});
Register file
// register.js file code
import { apiUrl } from './api';
try {
const resp = await apiUrl.post('/api/register', {
username,
email,
password,
});
const { data, status } = resp;
if (Object.keys(data).length && status === 200) {
// received api data successfully
console.log('API response', data);
}
} catch (err) {
console.log(err);
}
// For auth request
try {
const token = localstorage.getItem('token');
const res = await apiUrl.post(
'/authroute',
{
name: fullName,
originCountry: country,
career: careerStatus,
},
{
headers: { Authorization: `Bearer ${token}` },
}
);
const { data, status } = strapiRes;
if (Object.keys(data).length && status === 200) {
return res.status(status).json(data);
}
} catch (error) {
throw new Error(error);
}
// same for all request
apiUrl.get(endpoint);
apiUrl.post(endpoint, body);
apiUrl.put(endpoint, body);
apiUrl.delete(endpoint, body);
I'm making OCR app using amazon. App I'm doing using react native. And I have an error on the moment when I send data.
Error:
{
"code": "InvalidImageUrl",
"requestId": "c495b0d7-a65a-4138-97a9-2b1cb25dced8",
"message": "Image URL is badly formatted."
}
Why? What am I doing wrong? Code:
// ...
selectImage() {
ImagePicker.showImagePicker(options, (response) => {
if (response.didCancel) {
console.log('User cancelled image picker');
} else if (response.error) {
console.log('ImagePicker Error: ', response.error);
} else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
} else {
const source = { uri: response.uri };
this.setState({ imageSource: source });
this.extractText(response.uri);
}
});
}
extractText = async (imageSource) => {
// alert(imageSource)
let subscriptionKey = ['CODE'];
let endpoint = ['ENDPOINT']
if (!subscriptionKey) { throw new Error('Set your environment variables for your subscription key and endpoint.'); }
var uriBase = endpoint + "vision/v2.1/ocr";
// Request parameters.
// Display the image.
var sourceImageUrl = imageSource;
const data = new FormData();
data.append(imageSource);
fetch(uriBase + "?" + {
"language": "unk",
"detectOrientation": "true",
},
{
method: 'POST',
headers:
{
'Content-Type': 'application/json',
'Ocp-Apim-Subscription-Key': subscriptionKey,
},
body: '{"url": ' + '"' + data + '"}',
}).then((response) => response.json()).then((data) =>
{
console.log(JSON.stringify(data, null, 2));
}).catch((error) =>
{
console.log(error);
});
};
}
export default ImagePickerScreen;
Based on your code,there is something wrong with your data,it should an image URL so that Azure Version service can access it . I am not quite sure that how you get data in your custom logic . But anyway , this snippet below works , pls have a try :
const data = 'https://stanstroage.blob.core.windows.net/container2/personPic.jpg';
let subscriptionKey = '<key>';
let endpoint = '<endpoint>';
if (!subscriptionKey) { throw new Error('Set your environment variables for your subscription key and endpoint.'); }
var uriBase = endpoint + "vision/v2.1/ocr";
fetch(uriBase + "?" + {
"language": "unk",
"detectOrientation": "true",
},
{
method: 'POST',
headers:
{
'Content-Type': 'application/json',
'Ocp-Apim-Subscription-Key': subscriptionKey,
},
body: '{"url": ' + '"' + data + '"}',
}).then((response) => response.json()).then((data) =>
{
console.log(JSON.stringify(data, null, 2));
}).catch((error) =>
{
console.log(error);
});
Result:
If you want to upload a local image, you should use application/octet-stream as request content-type and set image content buffer as request body.
You can use react-native-fs to read your local image content and use buffer to get image content buffer and post it to Azure side , try snippet below below :
let subscriptionKey = '<key>';
let endpoint = '<endpoint>';
let fileUri = '<fileUri>';
let base64 = await fs.readFile(fileUri, 'base64');
let data = Buffer.from(base64, 'base64');
console.log(data);
if (!subscriptionKey) { throw new Error('Set your environment variables for your subscription key and endpoint.'); }
var uriBase = endpoint + "vision/v2.1/ocr";
fetch(uriBase + "?" + {
"language": "unk",
"detectOrientation": "true",
},
{
method: 'POST',
headers:
{
'Content-Type': 'application/octet-stream',
'Ocp-Apim-Subscription-Key': subscriptionKey,
},
body: data,
}).then((response) => response.json()).then((data) =>
{
console.log(JSON.stringify(data, null, 2));
}).catch((error) =>
{
console.log(error);
});
Result :
In my react app i am using axios to perform the REST api requests.
But it's unable to send the Authorization header with the request.
Here is my code:
This is authentication.js
async login(data) {
try {
const res = await axios.post(`'http://localhost:5000'/api/login`, data);
this.subject.next(true);
return res;
} catch (error) {
throw error;
}
}
This is login.js
async handleSubmit(e) {
e.preventDefault();
try {
const res = await auth.login(this.state.data);
tokenService.saveToken(res.data.token);
this.setState({});
swal({
title: "Good job!",
text: "Login successfully!",
icon: "success",
});
}
catch (error) {
swal({
title: "incorrect or password!",
text: "Login failed!",
icon: "error",
});
}
}
You can use Axios to create an instance of it with the headers passed to it save in local storage. Then, use that instance to further make requests. In this way, you don't to include it in every request.
const instance = axios.create({
baseURL: 'https://some-domain.com/api/',
headers: {'Authorization': bearer <TOKEN_FROM_LOCALSTORAGE>}
});
Use the instance to make request
instance.get("users")
.then(res => {
console.log(res);
console.log(res.data);
})
You can use this instance and customize it according to your instance so that code won't repeat. For further reference
Store it in localstorage and then concatenate it with 'Bearer'
let bearer = 'Bearer ' + JSON.parse(localStorage.getItem('token'));
//payload is the data which you're trying to send to the api endpoint
axios({
method: 'post',
url: '/api-endpoint',
headers: {
Authorization: bearer
},
data: payload
})
.then(response => response.json())
.then(json => json)
.catch(error => {
throw error;
});
check if the user is authenticated to use the Get or Post requests made by them
isAuthenticated() {
const token = localStorage.getItem('token');
}
Use the token to make the post request
axios({
method: 'post',
url: ''http://localhost:5000'/api/login',
{ headers: {"authorization" : token} }
data: payload
}),
.then(response => response.json())
.then(json => json)
.catch(error => {
throw error;
});
Handle your login
async handleSubmit(e) {
e.preventDefault();
try {
const res = await auth.login(this.state.data);
tokenService.saveToken(res.data.token);
this.setState({});
swal({
title: "Good job!",
text: "Login successfully!",
icon: "success",
});
}
catch (error) {
swal({
title: "incorrect or password!",
text: "Login failed!",
icon: "error",
});
}
}
Why you don't use axios interceptors like this:
axiosInstance.interceptors.request.use(
config => {
config.headers.authorization = localStorage.getItem("token");
return config;
},
error => Promise.reject(error)
);
Or declared on https://github.com/axios/axios/issues/1383
I am using react native document picker library to upload documents to the server my code is working perfectly but the issue is i want to show list of these selected images/documents i am not sure how to perform that action here is my code....
Document Selection code:
pickMultiple() {
try {
DocumentPicker.pickMultiple({
})
.then(images => {
this.setState({
image: null,
images: images
});
//console.log(images.length);
})
.catch(e => alert(e));
} catch (err) {
if (DocumentPicker.isCancel(err)) {
// User cancelled the picker, exit any dialogs or menus and move on
} else {
throw err;
}
}
}
Form Uploading code:
SubmitProposal = async () => {
const Uid = await AsyncStorage.getItem("projectUid");
const { params } = this.props.navigation.state;
const { amount, Description, DurationListKnown, images } = this.state;
console.log(
amount,
Description,
DurationListKnown[0],
images,
params.job_id,
images.length,
Uid
);
const formData = new FormData();
formData.append('user_id' , Uid);
formData.append('project_id' , params.job_id);
formData.append('proposed_amount' , amount);
formData.append('proposed_time' , DurationListKnown[0]);
formData.append('proposed_content' , Description);
formData.append('size' , images.length);
//formData.append('proposal_files' , images);
images.forEach((item, i) => {
// propertyData.description = this.props.description
var path = item.uri;
// var filename = path.substring(path.lastIndexOf('/')+1);
var filename = item.name;
formData.append("proposal_files"+i, {
uri: path,
type: item.type,
name: filename || `filename${i}.jpg`,
});
});
console.log(formData);
fetch('https://...proposal/add_proposal',{
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
},
body: formData
}).then(response => {
if (response.status == "200") {
console.log(response);
this.showSuccessAlert();
} else if (response.status == "203") {
console.log(response);
this.showAlert();
}
}).catch((error) => {
console.log(JSON.stringify( error));
});
};
kindly help me about how can i show list of these images/documents