Wait for an Axios call to finish in Quasar / Vue - javascript

I have a function in a Quasar application that needs to call an Web API that I need to wait until I get the results back to call the next function. I've posted my code and I'm sure that I'm missing some await or async or have them in the wrong place.
Global ex='';
testFunction3(arg){
console.log(arg)
} ,
testFunction2(){
this.ex = update_Members_data_term("#musc.edu");
},
async testFunction(){
await this.testFunction2()
this.testFunction3(this.ex)
},
API call:
function update_Members_data_term(term) {
axios.get(
'https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi', {
params: {
db: 'pubmed',
api_key: '',
retmode: 'json',
retmax: 200,
term: term
}
}
).then(async response => {
return response.data.esearchresult.idlist;
}).catch(error => {
console.log(error.response)
})
}
Thanks for the help.

testFunction2 Doesn't return a Promise so await does nothing. You are actually doing await null;
So the fix will be:
function update_Members_data_term(term) {
return new Promise((resolve,reject) => {
axios.get(
'https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi', {
params: {
db: 'pubmed',
api_key: '',
retmode: 'json',
retmax: 200,
term: term
}
}
).then(async response => {
resolve(response.data.esearchresult.idlist);
}).catch(error => {
reject(error.response)
})
});
}
async testFunction2(){
this.ex = await update_Members_data_term("email_here");
},
Note that you might just await axios.get instead of returning a Promise, but I'm not sure what the syntax is.

Related

Resolve promises created within Array.map on a timeout

I'm trying to resolve an array of promises using a timeout to avoid rate limit exceptions on API requests. However, I'm still hitting the rate limit, as the timeout doesn't seem to be working.
Not really sure how to make this work.
router.route("/").put(async (req, res) => {
const { apiKey: access_token, course, assignments } = req.body;
try {
const returnedIds = [];
const promises = await assignments.map((assignment) => {
return axios({
method: "PUT",
url: `https://url.to.api/api/v1/courses/${course}/assignments/${assignment.id}`,
params: {
access_token,
},
data: {
assignment: {
points_possible: assignment.points_possible,
},
},
});
});
const promiseResolution = function() {
Promise.all([...promises]).then((values) => {
values.forEach((_, index) => {
returnedIds.push(assignments[index].id);
});
res.status(201).json({
returnedIds,
});
});
};
setTimeout(promiseResolution, 5000);
} catch (e) {
res.status(401);
}
});
If you just want to put some time between API calls this should do.
router.route("/").put(async (req, res) => {
const { apiKey, course, assignments } = req.body;
try {
const returnedIds = [];
for (const assignment of assignments) {
returnedIds.push(await loadID(apiKey, course, assignment));
await wait(5000);
}
res.status(201).json({ returnedIds })
} catch (e) {
res.status(401);
}
});
function wait(duration) {
return new Promise((resolve) => setTimeout(resolve, duration));
}
function loadID(apiKey, course, assignment) {
// Makes the request, parses out the stuff you want from the response...
}
I would caution against using Promise.all since you probably want to check the result of each request before making the next one. For example, if the third request gets rate limited, you probably shouldn't bother making further requests.
It's because Promise.all will fire all promises at once, so your setTimeout is just set a timeout for all promises not individual promise as well.
You should try to make delay for each promise:
const promises = await assignments.map((assignment) => {
// some delay function
return axios({
method: "PUT",
url: `https://url.to.api/api/v1/courses/${course}/assignments/${assignment.id}`,
params: {
access_token,
},
data: {
assignment: {
points_possible: assignment.points_possible,
},
},
});
});
You can try this: (It's React but you should only focus on fetchData function) and see the logs:
https://codesandbox.io/s/zen-feynman-ql833?file=/src/App.js

Nodejs axios http request loop

I've a problem with Axios and foreach loop. My Api provider support only 5 contemporary call so I want call one by one but when execute this code the each body not wait the the finish call function and receive the error code 429. How can resolve this? thanks.
async function call(url) {
var options = {
method: 'GET',
url: url,
auth: {
username: '*****',
password: '*****'
}
};
var response = await axios.request(options);
print(response.data["Id"])
}
app.get('/save', async (req, res) => {
var options = {
method: 'GET',
url: 'getListUser',
auth: {
username: '***',
password: '***'
}
};
var response = await axios.request(options);
response.data["users"].forEach( async (val) => {
console.log("ENTER");
var url = 'getDetailUser' + val["id"];
var res = await call(url); // <- How to wait finish this?
console.log("EXIT")
}, (err) => {
console.log(err)
})
res.status(200).send("ok").end();
});
FYI, Promise couldn't work with loop that involves callback ie forEach. Alternatively, you could use for of
try {
for (const val of response.data['users']) {
console.log("ENTER");
var url = 'getDetailUser' + val["id"];
var res = await call(url);
console.log("EXIT")
}
} catch (error) {
console.log(error)
}
I would say answer by #Ifaruki is correct with a minor change
await Promise.allSettled(response.data["users"].map(val => {
var url = 'getDetailUser' + val["id"];
return call(url);
}))
For details check the difference. In some cases Promise.all might work but if any of the Promise fails, the whole result of Promise.all will be a rejection.
The code 429 can be resolved by looking at 429 Too Many Requests
Promise.all() is the way
await Promise.all(response.data["users"].map(val => {
var url = 'getDetailUser' + val["id"];
return call(url);
}))

dispatching Asynchronous action from an array react redux thunk

As per the requirement we need to make API call from the array list.Have used redux-thunk for async operation.Having issues while passing the request parameter to the reducer after api call is finished.
# From the container
let document = [ bankstatement1,bankstatement2];
document.map(element => {
dispatch ( actions.uploadFiles(element) )
});
# inside actions
export const uploadFiles = (payload) => {
return async dispatch => {
const response = await callAPIMiddleware(dispatch, {
types: ['DOC_UPLOAD_START','DOC_UPLOAD_SUCCESS','DOC_UPLOAD_ERROR'],
endPoint: ApiEndpoints.DOCUMENT_UPLOAD,
type: HTTP_METHOD_TYPE.POST,
payload: payload,
headers: Headers.multipart,
});
return response;
};
};
# inside axios middle ware
export const callAPIMiddleware = async (dispatch, RequestParams) => {
# calling upload_start ,here also the request payload being asked.
dispatch({
type: "DOC_UPLOAD_START,
data:RequestParams //bankstatement1,bankstatement2
});
# let res = await axios.post(endPoint,RequestParams, {
headers: reqHeaders,
config: reqConfig,
});
if (res && res.data) {
dispatch({
type:'DOC_UPLOAD_SUCCESS',
data: res.data,
param:RequestParams //bankstatement2,bankstatement2 here it is always referring to "bankstatement2"
});
}
After the API call is finished, reference to first request parameter is overridden by second one.Can anyone suggest how we can still refer to the first element .
EDITED:
what if you try to place the last piece of logic in "then" so it surely scoped there?
axios.post(endPoint,RequestParams, {
headers: reqHeaders,
config: reqConfig,
}).then(res => {
console.log('calling dispatch for ', RequestParams);
if (res && res.data) {
dispatch({
type:'DOC_UPLOAD_SUCCESS',
data: res.data,
param: RequestParams,
});
} else {
console.log('oops no result for ', RequestParams);
}
})

Promise object not returning a value

I am trying to get the value of asset:
const asset = getAssetInformation(11002);
function getAssetInformation(id) {
return axios({
method: 'GET',
url: "/asset-information",
params: {assetId: id}
});
}
console.log(asset);
The result is:
[object Promise]
How do I get the returned value from the request?
Using async and await is a practical way -
function axios(query) { // fake axios, for demo
return new Promise (r =>
setTimeout(r, 1000, { asset: query.params.assetId })
)
}
function getAssetInformation(id) {
return axios({
method: 'GET',
url: "/asset-information",
params: {assetId: id}
})
}
async function main() { // async
const asset = await getAssetInformation (11022) // await
console.log(asset)
}
main()
// 1 second later ...
// { asset: 11022 }
You will need to use .then function.
const asset = getAssetInformation(11002)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
Promises return another promise.
The way to unpack and work with a promise is through the .then() function, which will run after the promise returns.
const asset = getAssetInformation(11002);
function getAssetInformation(id) {
return axios({
method: 'GET',
url: "/asset-information",
params: {assetId: id}
});
}
Asset here is a promise, you want to use a then on it to get the value.
Instead of..
const asset = getAssetInformation(11002);
use
getAssetInformation(11002)
.then((response) => {
//What you returned will be here, use response.data to get your data out.
} )
.catch((err) => {
//if there is an error returned, put behavior here.
})

Getting chained Promise response

I'm having some problems getting a response from a chained Promise.
I have my component where the chain starts
component
componentDidMount = async ()=> {
try{
const products = await post('payments/getProducts', {});
console.log(products);
} catch(e) {
console.log(e)
}
}
This component calls my API helper:
async function post(url, data) {
token = null;
if (firebase.auth().currentUser) {
token = await firebase.auth().currentUser.getIdToken();
}
try {
const response = axios({
method: 'POST',
headers: {
Authorization: `${token}`,
},
data,
url: `${API_URL}${url}`,
})
return response;
} catch(e){
Promise.reject(e);
}
}
and my API Helper then calls a Firebase Cloud Function which calls Stripe:
paymentRouter.post('/getProducts', (req, res) => {
return stripe.products.list()
.then(products => {
console.log(products.data)
return products.data;
})
.catch(e => {
throw new functions.https.HttpsError('unknown', err.message, e);
})
})
Calling the function is no problem, and my Cloud Function logs out the product data, but I can't get the response to log in my API Helper nor my component.
Promise.reject(e);
That is completely senseless as it creates a new rejected promise that is not used anywhere. You could await it so that it gets chained into the promise returned by the async function, or you just return the promise from axios:
async function post(url, data) {
let token = null; // always declare variables!
if (firebase.auth().currentUser) {
token = await firebase.auth().currentUser.getIdToken();
}
return axios({
method: 'POST',
headers: {
Authorization: `${token}`,
},
data,
url: `${API_URL}${url}`,
});
}
Now the errors don't go into nowhere anymore and you can probably debug the problem :)

Categories

Resources