How to dynamic call the axios method in VueJS/NuxtJs - javascript

I'm trying to optimize my code. So, I dynamically use the axios function, but the returned response is a pending console log. I am using async/await. Any one can help me for this.
This is my code:
methods: {
getAgentsNames() {
const data = this.callAxios('get', `/getAllAgents`)
console.log(data) // returns pending
this.agents = data.listings
},
async callAxios(method, url, paramsBody = null) {
try {
const response = await this.$axios({
method,
url,
params: paramsBody,
headers: this.headers,
})
console.log(response) // success and have response data.
if (response.data.status == 'ok') {
return response.data
} else {
ifNotOK(response, this.$cookies)
return null
}
} catch (error) {
console.log(error)
return null
}
},
},

Your top function also needs to wait for the call to return:
async getAgentsNames() {
let data = await this.callAxios(

Related

Return of validate function not working with axios

I am trying to make a form, where users can change their email address of the account. I want them to enter their password to validate them. So I have a function that is doing the email change, but before it calls the validate function. If the return value is true it goes on. If not an error appears. But when testing it with the correct credentials it always goes into the else although i get a valid axios response.
emailChange() {
if (this.validate() == true) {
var data = JSON.stringify({
email: this.email,
});
this.put(data);
} else {
this.error = "Falsches Passwort";
this.snackbar = true;
}
},
validate() {
var data = JSON.stringify({
identifier: this.loggedInUser.email,
password: "123456",
});
var config = {
method: "post",
url: "http://192.168.190.112:1337/api/auth/local",
headers: {
"Content-Type": "application/json",
},
data: data,
};
this.$axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.then(function () {
return true;
})
.catch(function (error) {
console.log(error);
});
},
The function return is not returning to validate. Axios is asynchronous and you need either a promise or a callback.
this.$axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.then(function () {
return true; // this does not return to validate(). it returns just here
})
.catch(function (error) {
console.log(error);
});
This is a way to implement it.
emailChange() {
this.validate((error, isValid) => {
if (isValid) {
var data = JSON.stringify({
email: this.email,
});
this.put(data);
} else {
this.error = "Falsches Passwort";
this.snackbar = true;
}
})
},
validate(callback) {
var data = JSON.stringify({
identifier: this.loggedInUser.email,
password: "123456",
});
var config = {
method: "post",
url: "http://192.168.190.112:1337/api/auth/local",
headers: {
"Content-Type": "application/json",
},
data: data,
};
this.$axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.then(function () {
callback(null, true);
})
.catch(function (error) {
callback(error);
});
}
I think you're misunderstanding the purpose of .then().
Creating a request isn't instant, and it's completion depends on the server you're requesting data from to send you back a response. Because of this, axios uses asynchronous code to give you a Promise that will resolve after the request is complete.
The callback within the .then() function is called whenever the request is resolved (which could take multiple seconds with a slow connection).
The callback that contains your return statement could be called multiple seconds after your validate function ends, which isn't what you want.
I'd suggest using async/await as an alternative.
Declaring a function as async makes it return a Promise no matter what, which is what you want, and await waits for a promise to resolve before continuing.
Here's a quick example
// This function returns a promise!
async validate() {
// axios.get() returns a promise, so we use await to wait until it's resolved
let response = await axios.get("url")
// return the data (this is not a promise)
// since the method is async, this will be automatically converted into a promise
// that will resolve when the method returns something
return response;
}
// you can only use "await" in async functions
async emailChange() {
// wait until this.validate() is finished before continuing
if(await this.validate() == true) {
// etc.
}
}
async/await is generally the preferred way to do this because it's much cleaner than chaining callbacks together with .then()
Hopefully this helps

How to return values from a nested Axios call?

I am trying to perform the below steps:
Step 1: Make Axios call to check if record exists in database.
Step 2: If the record does not exit then make a POST API call to create data and return POST response.
Step 3: If the record already exists then return the response from Step 1
Step 1 and Step 2 works fine and I am able to return the value from createProfileByUserIDNew. When code block for Step 3 gets executed then createProfileByUserIDNew is not returning any value.
Can someone tell me what am I doing wrong?
async createProfileByUserIDNew(data, email) {
const AuthStr = 'Bearer ' + getToken();
const response = await axios
.get(`${baseUrl}/buyer-profiles?user_email=${email}`, {
headers: { Authorization: AuthStr },
})
.then((response) => {
//*****This block return proper value in the next then
if (response.data.length === 0) {
return axios.post(`${baseUrl}/buyer-profiles`, data, {
headers: { Authorization: AuthStr },
});
//~~~~~~~This block return proper value in the next then
//*****This block does not return any value in the next then
} else {
return response //Return response from first axios call
}
//*****This block does not return any value in the next then
})
.then((response) => {
return (response); //Step 2 return the value but step 3 return undefined
})
.catch((error) => console.log(JSON.stringify(error)));
}
Calling the above method:
const ret = createProfileByUserIDNew(
data,
user.email
);
ret.then(function (response) {
console.log(response); //Setp 2 returns proper value but step 3 return undefined
this.setState({ buyerProfileId: response.items.id });
});
Remember that async/await is "syntactic sugar" for the other promise syntax of chaining .then(), .catch(), and .finally(); in other words, it allows you to handle these types of asynchronous operations in code that appears more synchronous.
const createProfileByUserIDNew = async (data, email) => {
const AuthStr = "Bearer " + getToken();
try {
// we're awaiting this response, so we don't need to chain a .then()
// we could even destructure response into the objects we'll need later,
// i.e. const { data } = await axios.get(...)
const response = await axios.get(
`${baseUrl}/buyer-profiles?user_email=${email}`,
{
headers: { Authorization: AuthStr },
}
);
if (response.data.length === 0) {
// do the things we need to do when we don't get the data we want
// once again, we don't have to chain a then() to this; you may
// have heard that 'return await' is redundant and causes some
// problems, but since we're in a try/catch it's ok
// see https://jakearchibald.com/2017/await-vs-return-vs-return-await/
return await axios.post(`${baseUrl}/buyer-profiles`, data, {
headers: { Authorization: AuthStr },
});
} else {
// the user exists, so we'll do other things, like maybe return the
// original response or something
return response;
}
} catch (error) {
console.error("We hit a snag:", error);
}
};
// now when we call this method (must be called from another async function), the same principles apply
const ret = await createProfileByUserIDNew(data, user.email);
console.log(ret);
This.setState({ buyerProfileId: ret.data.items.id });
That happens because when you simply do return response you're returning the response of the request, not a Promise. You should only chain the .then() when making the axios.post() call since that actually returns a Promise.
Also, if you want to use the createProfileByUserIDNew function the way you are currently you need to return the Promise from axios.get directly.
async createProfileByUserIDNew(data, email) {
const AuthStr = 'Bearer ' + getToken();
return axios.get(`${baseUrl}/buyer-profiles?user_email=${email}`, {
headers: { Authorization: AuthStr },
})
.then((response) => {
if (response.data.length === 0) {
return axios.post(`${baseUrl}/buyer-profiles`, data, {
headers: { Authorization: AuthStr },
})
.then((response) => {
return response;
});
} else {
return response;
}
})
.catch((error) => console.log(JSON.stringify(error)));
}

Async function immediately call then() in recursive function

I have a problem, I tried to use async function to make API call but then() doesn't wait until the async function return the promise.
async function :
async function FgetFloorplansByFolder (idProject,idFolder, data = [], hasMore = false, lastSyncedAt = null) {
axios.get(API_URL, {
params:{
'last_synced_at':lastSyncedAt
},
headers: {
'Authorization': API_TOKEN,
'Accept': 'application/json'
}
})
.then((response) => {
let XHasMore = response.headers['x-has-more'];
let lastSyncedAt = response.headers['x-last-synced-at'];
for(var i in response.data) {
if(response.data[i].folder_id != null || response.data[i].folder_id == idFolder){
data.push(response.data[i])
}
}
if(XHasMore == 'true'){
FgetFloorplansByFolder(idProject,idFolder, data, XHasMore, lastSyncedAt)
}
else {
console.log(data);
return data
}
})
.catch((err) => {
return Promise.reject(err)
})
}
call of async function :
await FgetFloorplansByFolder(req.params.idProject, req.params.idFolder)
.then((result) => {
console.log(result);
})
.catch((error)=>{
console.log(error);
})
The expected result is : then function in the call wait until getFloorplansByFolders finish his recursive call and return data before print result in then. But then is printing undefined and doesn't wait until async function finish his call.
How can I do ?
Nothing in the code tells the function that it should wait for that promise to settle, so it doesn't.
In general, don't mix async/await with .then/.catch/.finally (though there are exceptions), use one or the other.
In this case, you can either
Remove the async and just put return in front of the call to axios to return the promise chain; or
Switch to using await within the function
(In both cases, I strongly urge you to remove the .catch handler that converts rejection into fulfillment with undefined; instead, let the caller see the rejection so they know the operation failed.)
#1 looks something like this (note comments):
// 1. No `async`
function FgetFloorplansByFolder (idProject,idFolder, data = [], hasMore = false, lastSyncedAt = null) {
// 2. Return the promise chain
return axios.get(API_URL, {
params:{
'last_synced_at':lastSyncedAt
},
headers: {
'Authorization': API_TOKEN,
'Accept': 'application/json'
}
})
.then((response) => {
let XHasMore = response.headers['x-has-more'];
let lastSyncedAt = response.headers['x-last-synced-at'];
for(var i in response.data) {
if(response.data[i].folder_id != null || response.data[i].folder_id == idFolder){
data.push(response.data[i])
}
}
if(XHasMore == 'true'){
// 3. Return the promise from the recursive call
return FgetFloorplansByFolder(idProject,idFolder, data, XHasMore, lastSyncedAt)
}
else {
console.log(data);
return data
}
});
// 4. Don't put a `.catch` here -- let the caller know the operation failed
}
#2 looks something like this:
async function FgetFloorplansByFolder (idProject,idFolder, data = [], hasMore = false, lastSyncedAt = null) {
const response = await axios.get(API_URL, {
params:{
'last_synced_at':lastSyncedAt
},
headers: {
'Authorization': API_TOKEN,
'Accept': 'application/json'
}
});
let XHasMore = response.headers['x-has-more'];
let lastSyncedAt = response.headers['x-last-synced-at'];
for(var i in response.data) {
if(response.data[i].folder_id != null || response.data[i].folder_id == idFolder){
data.push(response.data[i])
}
}
if(XHasMore == 'true'){
// 3. Return the result of the recursive call
return FgetFloorplansByFolder(idProject,idFolder, data, XHasMore, lastSyncedAt)
}
else {
console.log(data);
return data;
}
}

How do i retrieve data from Async storage and use it in my component?

I have saved a user_id and token in Async storage and i can retrieve it in via console log. with the retrive function. So i know the set function is working perfectly, the functions in deviceStorage all Async.
The problem comes when trying to use the retrieved user_id & token in my component it returns undefined.
How can i get an item from storage and use it later in my code, i want to use the token and userid for a fetch request. Please help me and highlight the best way to do.
import deviceStorage from "../components/services/deviceStorage";
class Jobs extends Component {
constructor() {
super();
this.state = {
jobsData: [],
isLoading: true
};
}
componentDidMount() {
deviceStorage.retrieveToken().then(token => {
this.setState({
token: token
});
});
deviceStorage.retrieveUserId().then(user_id => {
this.setState({
user_id: user_id
});
});
const opts = {
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: "Token " + this.state.token
}
};
fetch("http://example.com/job/" + this.user_id, opts)
.then(res => res.json())
.then(jobs => {
this.setState({
jobsData: jobs,
isLoading: false
});
console.log(jobsData);
})
.catch(error => {
console.error(error);
});
}
render {}
Code for the retrieve and set
import {AsyncStorage} from 'react-native';
const deviceStorage = {
async storeItem(key, item) {
try {
//we want to wait for the Promise returned by AsyncStorage.setItem()
//to be resolved to the actual value before returning the value
var jsonOfItem = await AsyncStorage.setItem(key, JSON.stringify(item));
return jsonOfItem;
} catch (error) {
console.log(error.message);
}
},
async retrieveItem(key) {
try {
const retrievedItem = await AsyncStorage.getItem(key);
const item = JSON.parse(retrievedItem);
// console.log(item);
return item;
} catch (error) {
console.log(error.message);
}
return
}
};
export default deviceStorage;`
There are two ways to get the data stored in async storage:
(1) Promise method. Here your code does not wait for the block to finish and returns promise which is accompanied by .then clause if the promise resolves and .catch clause if there is error.
(2) Async and Await method. This is more preferred, here your code waits for the execution before proceeding one of the example to refer is below:
retrieveData() {
AsyncStorage.getItem("id").then(value => {
if(value == null){
//If value is not set or your async storage is empty
}
else{
//Process your data
}
})
.catch(err => {
// Add some error handling
});
Second Method example:
async retrieveData() {
try {
let value = await AsyncStorage.getItem("id");
if (value !== null) {
//you have your data in value variable
return value;
}
}
catch (error) {
// Error retrieving data
}
}
your retrieve data storage methods should look like this
retrieveData = async () => {
try {
const value = await AsyncStorage.getItem('TASKS');
if (value !== null) {
// We have data!!
return value;
}
} catch (error) {
// Error retrieving data
}
return null;
};
Adding to the previous solutions
//function to retrieve data
async function retrieveItem(key) {
try {
const retrievedItem = await AsyncStorage.getItem(key); //dataType String
const item = JSON.parse(retrievedItem);//dataType object
return item;
} catch (error) {
console.log(error.message);
}
return
}
//function call
retrieveItem(key).then((value) => {
//unlike normal function call, this waits for the promise to complete
return value;// actual value not the promise
})
.catch((error) => {
console.log('Error: ' + error);
});

How to handle null response in fetch api

I building a react-native app and using fetch api for handling server request, it is working fine if json returned from the server is not null, but if the response from the server is null it will give me an error-"Json Parse error:Unexpected EOF", below is the code used by me for fetch, I tried to set break-point while debugging to see what is coming in response when null is returned from the server, I am unable to find something on which I can put some check and see if response is null before parsing it, so need help
return fetch(url, //service url{
method: type, // get or post
headers: {
'Accept': 'application/json',
'Content-Type': contentType,
},
body: data //some input parameters
}).then((response) => {
return response.json();
})
.then((responseJson) => {
request.onSuccess(responseJson); // success callback
})
.catch((error) => {
request.onError(error); // error callback
console.error(error);
});
There is a good answer here, but in my case I needed access to the response object after response.text() returns:
function buildResult(response) {
// response.json() crashes on null response bodies
// return {
// data: response.json(),
// identityToken: response.identityToken // sliding expiration...
// };
return new Promise((resolve, reject) => {
response.text().then(body => {
resolve({
data: body.length ? JSON.parse(body) : null,
identityToken: response.identityToken // sliding expiration...
});
}).catch(err => {
reject(err);
});
});
}
//
// the api fetch function
//
function apiFetch(url) {
return fetch(url)
.then(checkStatus)
.then(parseIdentityToken)
.then(buildResult);
}
If the json response null Instead of using response.json() use response.text()
fetch(path)
.then(function (response) {
return response.text()
}).then(function (data) {
resolve(data.length == 0 ? null : JSON.parse(data))
}).catch(err => {
reject(err);
})
If you want to сheck the response request for emptiness:
const response = await fetch(url, options); // your url and options
if (response.ok) {
const contentType = response.headers.get('content-type');
if (contentType && contentType.indexOf('application/json') !== -1) {
const json = await response.json();
successCb(json); // Write your script.
} else {
successCb(); // if the request is successful but the response is empty. Write your script.
}
}

Categories

Resources