I want to achieve the following using React-jsx:
In one file, I have a function that makes a database request and returns some data. In another file, I want to call this function and then process the data. I want to handle this operation preferably using async/await as I have seen it should be possible to do, but I am not against a promise-based solution. Here is what I did:
export async function getData() {
try {
await request
.get(url, (err, res) => {
console.log('1', res.body);
return res.body;
}
} catch(e) {
return e;
}
}
And in the second file, where I call getData():
import { getData } from './path';
async formatData() {
try {
const data = await getData();
// some formatting
console.log('2', data);
} catch(e) {
return e;
}
}
And here is the result I get in the console:
> '2' undefined
suggesting that await hasn't worked. What I am missing?
Related
I have an instance of axios with baseURL:"http....".
This instance is imported into data.js to be able to make all calls with axios in another file.
This is data.js:
import axios from 'src/utils/DataService';
function getEwo(id) {
return axios.get('api.../' + id);
}
function getorders(){
return axios.get("api/.../orders");
}
export{getEwo,getorders}
The first call is working, but the second one does not.
In the last file I have the following code:
import * as dataEwo from 'src/dataservice/dataEwo';
const getOrders = useCallback(async () => {
try {
const response = await dataEwo.getorders();
var resp = response.data.data;
if (isMountedRef.current) {
setOrders(resp);
}
} catch (err) {
console.error(err);
}
}, [isMountedRef]);
useEffect(() => {
getOrders();
}, []);
I tried getorders() on Swagger and from BE it returns the data correctly.
If I try to make the same call from the FE client with axios it doesn't work and the BE is queried but the query returns no data and no errors.
Why doesn't axios work in this case?
What I want to do :
I send the GET request through axios
I open a local Json file with fs.readfile
I process the data and return it
I want to display the data when it return with res.json
what actually happened
I send the GET request through axios
I open a local Json file with fs.readfile
They return the data before fs.readfile finished so it's undefined or blank
This one I put on the frontend and the controller
//frontend
const fetchRewards = async()=>{
let link ="/api/reward";
const {data} = await axios.get(link);
console.log(data); **// this one logging undefined**
}
// on controller
async getRewardsById(req,res,next) {
try {
const result = await rewardService.getReward();
res.json(result);
} catch (error) {
next(error);
}
},
This is my service
const getReward = async () => {
fs.readFile("test.json", (err, inputData) => {
return {"name":"John", "age":30, "car":null};
}
console.log("done");
}
Seems to me like you are not returning anything from your service?
Try returning the fs.readFile.
export const deleteComment = (id) => {
console.log("id", id);
return async (dispatch) => {
try {
const response = await axios.delete(
`http://localhost:5000/comments/${id}`
);
console.log("response", response);
dispatch(actions.DeleteCommentAction(id));
} catch (err) {
console.log(err);
}
};
};
For some reasons, this code does not work. When i use this acton the console.log("id",id) is being executed, but console.log with response is not. I tested my route for deleting in Postman and everything works, does anyone know what is this happening?
Route for deleting, but as i said. It work, it some issue in React i guess:
router.delete("/:id", async (req, res) => {
const id = req.params.id;
try {
Comment.findByIdAndDelete(id, function (error, response) {
if (error) {
return res.send(error);
}
console.log(response);
return res.send(response);
});
} catch (error) {
return res.send(error);
}
});
Have you inspected the network tab to see if the request was sent?
Can you share the component where you are invoking deleteComment?
And perhaps try to simplify and execute the deletion outside the deleteComment method, it might be you are not injecting the dispatch method into the anonymous function.
The cause could also related to redux. I guess you are not using a redux middleware to handle the asynchronous executions as you are waiting the deletion, which could be a possible scenario for the issue. And maybe you could consider adding one of those middlewares like reduxk-thunk or redux-saga for example.
I actually forgot to add:
const mapDispatchToProps = {
deleteComment,
};
I tried to put POST by AXIOS function inside another function to reuse it multiple times. but unfortunately It doesn't work as I expected (which was working using FETCH),
AXIOS CALL JS:
export async function post(apiRoute, body) {
try {
body = JSON.stringify(body);
axios.post(apiRoute, body, httpOptions)
.then((res)=>{
console.log(res.data); // I have data here
return res.data;
});
}
catch (err) {
console.log(err);
return err;
}
}
And the caller is:
async DoLogin(userName, password) {
var data = await post(url,{ // post is axios method defined above in another file
UserName: userName,
Password: password
});
return data; // I have nothing here
}
And the problem is I got undefined in DoLogin but got data inside POST method, It seems the problem is related to timing, axions returns a promise which is not possible to read in DoLogin, how I can do this? I did this via FETCH and it works perfectly.
try using async-await in this way.
export async function post(apiRoute, body) {
try {
const response = await axios.post(apiRoute, body, httpOptions)
return response.data;
}
catch (err) {
return err;
}
}
When I make a "GET" request from the client to the server the server should make a axios.get() call to a stock API to retrieve data for an array of tickers. When I console.log the results it seems to be working fine but the array doesn't seem to save, like it gets wiped out and comes back to the client as empty. I think I might be messing this up with async/await.
async function currentPrice(ticker) {
const apiURL = `https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=${ticker}&apikey=${API_KEY}`;
let price;
await axios.get(apiURL).then(data => {
try {
price = data.data["Global Quote"]["05. price"];
} catch (error) {
console.log(error)
}
})
return price;
};
app.get("/refresh", redirectLogin, (req, res) => {
const {
user
} = res.locals;
var array = [];
connection.query(`SELECT * FROM holdings WHERE user_name = '${user.user_name}' AND quantity > 0`, (err, results) => {
if (err) throw err;
results.forEach(holding => {
currentPrice(holding.ticker).then(data => {
var updatedTicker = {
ticker: holding.ticker,
description: holding.description,
price_acquired: holding.price_acquired,
market_price: data,
delta: parseFloat(this.market_price) - parseFloat(this.price_acquired),
quantity: holding.quantity,
trade_date: holding.date_acquired
}
array.push(updatedTicker);
// console.log(array);
console.log(updatedTicker.market_price)
})
})
res.json(array)
})
})
You are calling res.json(array) before any of your currentPrice().then(...) calls have finished, thus the array is still empty.
There are a number of different ways to solve this. Probably the simplest is to change for .forEach() loop to a plain for loop and then use async/await to serialize each of your calls to currentPrice():
function currentPrice(ticker) {
const apiURL = `https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=${ticker}&apikey=${API_KEY}`;
return axios.get(apiURL).then(data => {
try {
return data.data["Global Quote"]["05. price"];
}
catch (error) {
console.log(error);
throw error;
}
});
}
app.get("/refresh", redirectLogin, (req, res) => {
const { user } = res.locals;
connection.query(`SELECT * FROM holdings WHERE user_name = '${user.user_name}' AND quantity > 0`, async (err, results) => {
if (err) {
console.log(err);
res.sendStatus(500);
return;
}
try {
const array = [];
for (let holding of results) {
let data = await currentPrice(holding.ticker);
let updatedTicker = {
ticker: holding.ticker,
description: holding.description,
price_acquired: holding.price_acquired,
market_price: data,
delta: parseFloat(this.market_price) - parseFloat(this.price_acquired),
quantity: holding.quantity,
trade_date: holding.date_acquired
}
array.push(updatedTicker);
}
res.json(array);
} catch(e) {
console.log(e);
res.sendStatus(500);
}
});
});
Various changes:
Simplified the currentPrice() function to just return the axios promise directly
Appropriately reject in currentPrice() if there's an error so the caller sees the error.
Add proper error handling (sending an error response), if the db query fails.
Switch .forEach() loop to a for loop so we can use await to serialize the calls to currentPrice() so we can more easily know when they are all done.
Add error handling and sending of an error response if currentPrice() has an error.
Call res.json(array) only after all the now-serialized calls to await currentPrice() have completed.
FYI, a fully complete transformation here would switch to mysql2 so you can use the promise interface for connection.query() rather than the plain callback interface that you are using now. That would allow you to consolidate error handling to one place more easily.