How to do asynchronous calls in vanilla javascript - javascript

I managed to use axios by putting this link in my html:
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
What I am trying to do is call axios twice, once to call my http request to send in a JSON Object, and another to send in a file along with the JSON object. What I want to do is to make it so that it is required for both to be sent, meaning that the user cannot just send the JSON object by itself or the file by itself. However, my code does not check for that for some reason. I believe it is due to async not being present, But idk how to add that when I am using vanilla js. Here is my code:
axios.post('/account/signup', userObj).then((profile)=>{
//data returns current user info, including if they are verified or not
return axios.post('/account/signup/veteranFile-upload', formData)
}).then(()=>{
//window.location.replace('/')
console.log('Hello?')
}).catch( function (error){
showAppropriateTextSignUp(error.response.data, signupErr)
})
For some extra info, my model requires the file and the JSON data being sent.

your second then is in the wrong place. also is formData defined?
axios.post('/account/signup', userObj).then((profile)=>{
//data returns current user info, including if they are verified or not
return axios.post('/account/signup/veteranFile-upload', formData).then(()=>{
//window.location.replace('/')
console.log('Hello?')
}).catch( function (error){
showAppropriateTextSignUp(error.response.data, signupErr)
});
});
a much cleaner way: use async await:
const api = async() => {
try{
const profile = await axios.post('/account/signup', userObj);
const whatever = axios.post('/account/signup/veteranFile-upload', formData);
console.log(whatever)
} catch (e) {
showAppropriateTextSignUp(error.response.data, signupErr)
}
}

you might need to chain the axios call instead of returning. That is
axios.post('/account/signup', userObj)
.then((profile)=>{
//current user info, including if they are verified or not
axios.post('/account/signup/veteranFile-upload', formData).then(resp=>{
//do something with the response
//window.location.replace('/')
}).catch(err=>{
console.log(err)
})
console.log('Hello?')
}).catch( function (error){
showAppropriateTextSignUp(error.response.data, signupErr)
})

Related

async or promise all, reject all if first fails - 3 post method calls

Edited. I need to call addUser() to receive the userId back thats generated from the database. Then i need to call addTicket() with the userId to receive the ticketId back thats generated from the database. Then finally call addToBooks with the userId and ticketId. These are all post methods, the only data I need back from each call are their ids, the last post method will return full data. Is there a way to handle this where I can fail all post methods if any one of the fails in the process? I've seen examples of promise.all that can do this but it was all for get methods.
You could try something like this, following your functions names example:
const getData = async () => {
try {
const userId = await addUser();
if(userId) {
const ticketId = await addTicket(userId);
const response = await addToBooks(userId, ticketId);
return response;
} else {
throw new Error("Error getting data")
}
} catch(error) {
console.log(error);
}
}
This doesn't use Promise.all, but since the example you are giving, to my understanding, only needs the userId to complete the other 2 operations, I think this should work

Handling a success in JS

I am experimenting with t library, and am trying to install the functionality into my own search bar to practice (still a student).
Can anyone provide advice to the format this would be in??
#PascalLamers answer is the cleanest way to go about it, using the "await" pattern.
To see what this looks like with promise chaining:
app.get('/:url', async function (req, res) {
return wappalyzer
.init()
.then(function(){
return wappalyzer.open(decodeURIComponent(req.params.url))
})
.then(function(site){
return site.analyze()
})
.then(function(data){
return res.status(200).json(data);
})
.catch(function(err){
return res.status(500).json({ message : err.message })
})
}
Each then executes a single async operation, and on success passes its result to the next then() operation.
Each then() is only called upon the success of the previous then(). If an error occurs at any point, the catch() is executed and the function returns (in this case, returns an error 500).
Completely ignoring what wappalyzer actually is or does, I would suggest the following, since you are already providing an async function as callback to your route controller :
app.get('/:url', async function (req, res) {
try {
await wappalyzer.init();
const site = await wappalyzer.open(decodeURIComponent(req.query.url));
const data = await site.analyze();
// if you end up here, everything was successfull
return res.status(200).json(data);
} catch (ex) {
// if you end up here, something went wrong
return res.status(500).json({ message : ex.message });
}
});
The above doesn't really make much sense, since you are telling your backend to look for an url param but using a query parameter instead. I woudln't recommend to send an url as either, param or query. Use the request body instead :
// receive request in backend, with an endpoint that makes a bit more sense
// also using POST method, otherwise you won't be able to send a body
app.post('/search', async function (req, res) {
const url = req.body.url;
// do stuff
});
// sending request to backend, using axios for example
const respond = await axios.post('/search', { url : 'www.google.com' });
// or using fetch
const respond = await fetch('/search', {
method: 'post',
body: JSON.stringify({ url : 'www.google.com' });
Please be aware these are just pointers, nothing to copy & paste :) .
If you are using Express, I suggest reading the documentation again. I think you are misunderstanding how the router works : https://expressjs.com/de/guide/routing.html#route-parameters

Returning Error Values Through Axios/Express To React App

I've got a handleSubmit function that fetches data from my backend as part of a larger component. I'd like to send the error information to my redux store and/or local component when the back-end fails, but am unable to do so.
The handleSubmit function looks like this (it's using React hooks, which are wired up correctly. Can post the full component if that is useful):
const handleSubmit = async (e, { dataSource, filter, filterTarget }) => {
e.preventDefault();
setIsLoading(true);
setErrorValue(null);
setError(false);
const token = localStorage.JWT_TOKEN;
const link = filterTarget === "Identifier" ? `http://localhost:8081/api/${dataSource}/${filter}`: `http://localhost:8081/api/${dataSource}?filter=${filter}&filterTarget=${filterTarget}`;
try {
let data = await axios.get(link, { headers: { authorization: token }});
props.setData(data);
setError(false);
setIsLoading(false);
} catch (err){
setErrorValue(err.message);
setError(true);
setIsLoading(false);
};
};
I'm intentionally making bad requests through the form, which will trigger an error in my backend. These are handled through my custom Express middleware function, which looks like this (I'll add more once I get this framework to work):
handleOtherError: (error, req, res, next) => { // Final custom error handler, with no conditions. No need to call next() here.
console.log("This error handler is firing!");
return res.status(500).json({
message: error.message,
type: "ServerError"
});
}
I know that this function is firing because the console.log statement is appearing on my server, and if I change the status code, so does the status code error on the front-end in my Google Chrome console.
In fact, if I go to the network tab, the correct error information appears for my request. Here's the video of me making a bad request:
However, when I try to access the err.message on my front-end, I'm not able to do so. The err.message in my try/catch handler for the handleSubmit function only ever gives me the Request failed with status code XXX
What am I doing wrong?
See https://github.com/axios/axios#handling-errors
You can access the response by using err.response.data.message, not err.message.
Found the answer posted elsewhere: https://github.com/axios/axios/issues/960
Apparently, to get the message, you have to use err.response.data.message
Simply using "err" will only give you a basic string respresentation of the error.

Data part of Response is a long script instead of desired json object

I am building a web app using laravel and vuejs. I have made a axios get request to get a list of users .
I am getting a Promise object, and from what i have read. Reason for getting a promise object is because it's an async request.
I have tried .then() to get data part of the response. But i am getting a huge script instead of desired data.
axios......then(function(response){
console.log(response.data);
})
Initially what i did was
var res = axios.get('/allUsers');
console.log(res)
That time i came to know about promise object and read about.
When i checked network in dev tools, status code is 200 and i can see list of users. So i guess my request is successfully completed.
What should be done to get the list of the users. That list i will be using to update my UI.
Depending on what you're getting back for data there are a few ways to handle this. You may need to convert the data after the you get receive the response.
axios.get('some_url')
.then(res => res.json())
.then(data => {
// do something with the data
}).catch(err) {
conosole.error(err);
}
if you're seeing the data come through properly in the response and you're getting what you need without doing that then just do
axios.get('some url').then(res => {
// do something in here with the data here
})
also make sure you're getting back json if that's what you're looking for. check your response to see if its html or json because they can be handled a bit differently
as an "Edit" you could also handle this with async await so you dont end up in callback hell
async function fetchData() {
try {
const res = await axios.get('some url');
// next step might not be necessary
const data = await res.json();
// do something with the data
console.log(data); // if converting it was necessary
console.log(res); // if not converting
} catch (err) {
console.error(err);
}
}

Why doesn't this async function throw undefined?

I have a pretty simple async function that calls the fetch api, and brings me back some data. I am using the await keyword 2 times in this function, and then getting that data and pushing it into my component state.
Here is my pseudo-code in regards to how this function is executing (please tell me if I'm right or wrong here):
Call the fetch api with await: this allows the rest of your code to continue to the next line.
Once you get the fetch the response stream, put it into data variable. Again, the code can continue while we are waiting for this to happen.
Log the data to the console.
Step 3 is where I have some questions...let's say I'm on a really terrible network, and my fetch request doesn't give me my data for 5 full seconds. At that point, shouldn't my console.log(data) line throw undefined, and execute the catch block, due to the async function allowing console.log(data to run BEFORE I get my fetch data back?
I tested this by going into the Chrome Web dev console, and selected the "slow 3g" connection. Even with that network, I was able to log my data to the console without throwing undefined.
What I want to do is to make sure there is data to push into state right after I get my data object back.
getMovieDetails = async id => {
const API_KEY = process.env.REACT_APP_API_KEY;
const movieId = id;
const url = `https://api.themoviedb.org/3/movie/${movieId}?api_key=${API_KEY}&language=en-US`;
try {
const response = await fetch(url);
const data = await response.json();
console.log(data);
this.setState({
title: data.title,
poster: data.poster_path
});
} catch (err) {
console.log(`Couldn't fetch the endpoint!`);
console.log(err);
}
};
You are wrong in the first point of your Pseudo-code
Call the fetch api with await: this allows the rest of your code to
continue to the next line.
Actually, no. await will block the execution of the next lines in the async function.
So,
yourAsyncFunction = async () => {
await doSomething();
console.log('done something') // Will not run until doSomething() gets completed
}
Which is why you are always getting the fetched data in your console.log(data) statement.

Categories

Resources