AsyncStorage in a non async function - javascript

The following code:
_loginAsync = async () => {
fetch('localhost:3000/login')
.then((response) => response.json())
.then((responseJson) => {
await AsyncStorage.setItem('my-item', responseJson.item);
this.props.navigation.navigate('Home');
})
.catch((error) => {
console.error(error);
});
}
throws the error: Can not use keyword 'await' outside an async function.
Which is the proper way to valorize the my-item?

Your .then callback isn't marked as async, only the outer _loginAsync function is.
_loginAsync = async () => {
fetch('localhost:3000/login')
.then((response) => response.json())
.then(async (responseJson) => {
await AsyncStorage.setItem('my-item', responseJson.item);
this.props.navigation.navigate('Home');
})
.catch((error) => {
console.error(error);
});
}
That said, it seems weird to mix all of the .then and await forms here.
Using Async/Await Only
I think this is the most readable version. We just use async/await to await the fetch directly instead of working with its promise.
_loginAsync = async () => {
try {
const response = await fetch('localhost:3000/login');
await AsyncStorage.setItem('my-item', response.json().item);
this.props.navigation.navigate("Home")
} catch(error) {
console.error(error);
}
}
Using Promises Directly
You can (pretty much) always use an async function as a normal function that returns a promise as well. So instead of awaiting AsyncStorage.setItem we can just use its promise as part of our chain by returning it from then.
_loginAsync = () => {
fetch('localhost:3000/login')
.then((response) => response.json())
.then((responseJson) => AsyncStorage.setItem('my-item', responseJson.item))
.then(() => this.props.navigation.navigate('Home'))
.catch((error) => {
console.error(error);
});
}

If you have to make it work for your code, make the anonymous function for the block where await occurs to async.
_loginAsync = async () => {
fetch('localhost:3000/login')
.then((response) => response.json())
.then(async (responseJson) => {
await AsyncStorage.setItem('my-item', responseJson.item);
this.props.navigation.navigate('Home');
})
.catch((error) => {
console.error(error);
});
}
But I prefer this is a much better approach and looks more readable. Try this code instead.
_loginAsync = async () => {
try {
const response = await fetch('localhost:3000/login');
const responseJson = response.json()
await AsyncStorage.setItem('my-item', responseJson.item);
this.props.navigation.navigate('Home');
} catch (error) {
console.error(error);
}
}

Related

How to resolve multiple then() promise into one

In this code I used multiple then() methods, I just want to convert it into only one then, How it is possible.
getGreeting = () => {
fetch(url)
.then((response) => response.json())
.then((result) => result.data)
.then((data) => printCards(data))
.catch((err) => {
console.log(err);
});
};
notice the async and await keywords
fetch(url)
.then(async (response) => {
const json = await response.json();
printCards(json.data);
})
.catch((err) => {
console.log(err);
});
};

Using async await with axios

I've got a function that makes a call with axios and returns it:
const makeRequest = () => {
return axios.get('/data');
}
const printResponse = () => {
makeRequest()
.then((response) => {
console.log(response)
})
.catch((error) => {
console.log(error)
})
}
I'm trying to use async await to make this better and avoid using 'then'.
const makeRequest = async () => {
return await axios.get('/data');
}
const printResponse = () => {
try {
const response = makeRequest();
console.log(response)
} catch(error) {
console.log(error)
}
}
However, despite using await, makeRequest still returns a promise, so I have to end up using then in my printResponse function anyway. Am I not using this correctly?
"However, despite using await, makeRequest still returns a promise"
Yes, of course it does. async/await is just syntactic sugar for working with Promises. In particular, any function marked async will return a Promise - this is by design.
If you don't like using .then, you can just as easily use async/await to consume this promise:
const printResponse = async () => {
try {
const response = await makeRequest();
console.log(response)
} catch(error) {
console.log(error)
}
}

Axios prints value on console but returns undefined

I have quite an issue for some time and is getting on my nerves and it doesn't make sense. I have used axios on my react frontend and it works perfect when assigning the get value to the state. But when using it in a normal javascript code, I appear to have this following issue: i can print the object's value in the console but it will return only undefined.. Here is my code:
login = () => {
let data;
axios.get('https://myaddress/authenticate')
.then(response => {
data = response;
console.log('data here', data);
})
.catch(error => {
console.error('auth.error', error);
});
console.log('eee', data);
return data;
};
Here we are talking about axios strictly.
You can't return an ajax response because it's asynchronous. You should wrap your function into a promise or pass a callback to login
UPDATE: As #Thilo said in the comments, async/await would be another option, but it will let you set the response to data tho ...
1. Wrap into a promise
login = () => new Promise((resolve, reject)=>{
axios.get('https://myaddress/authenticate')
.then(response => {
resolve(response)
})
.catch(error => {
reject(error)
});
});
// Usage example
login()
.then(response =>{
console.log(response)
})
.catch(error => {
console.log(error)
})
2. Pass a callback
login = (callback) => {
axios.get('https://myaddress/authenticate')
.then(response => {
callback(null,response)
})
.catch(error => {
callback(error,null)
});
};
// Usage example
login((err, response)=>{
if( err ){
throw err;
}
console.log(response);
})
3. Async/Await
login = async () => {
// You can use 'await' only in a function marked with 'async'
// You can set the response as value to 'data' by waiting for the promise to get resolved
let data = await axios.get('https://myaddress/authenticate');
// now you can use a "synchronous" data, only in the 'login' function ...
console.log('eee', data);
return data; // don't let this trick you, it's not the data value, it's a promise
};
// Outside usage
console.log( login() ); // this is pending promise
In ES7/ES8 you can do async/await like a boss:
login = () => {
return new Promise((resolve, reject) => {
axios.get('https://myaddress/authenticate')
.then(response => {
resolve(response)
})
.catch(error => {
console.error('auth.error', error);
reject(error)
});
});
};
async function getData() {
try{
const data = await login()
} catch(error){
// handle error
}
return data;
}
getData()
.then((data) => console.log(data));

react-native fetch async/await response filtering

I have response from my server like buildings : [record1, record2, ...] and I want to get only the array from that response. How can I get just the array from the Promise? I have tried some async/await things but I didn't understand how to use it in this code:
setupImpagination() {
....
fetch(pageOffset, pageSize, stats) {
return fetch(`http://localhost:3000/api/building/all?skip=${pageOffset}&limit=${pageSize}`)
.then(response => {
console.log('response.json() => ',response.json());
response.json()
})
.catch((error) => {
console.error(error);
});
}
});
}
.then way
fetch(pageOffset, pageSize, stats) {
return fetch(`http://localhost:3000/api/building/all?skip=${pageOffset}&limit=${pageSize}`)
.then(response => {
console.log('response.json() => ',response.json());
response.json()
}).then(responseJson => {
return responseJson.buildings
}).catch((error) => {
console.error(error);
});
}
});
async/await way:
async fetch(pageOffset, pageSize, stats) {
try {
const response = await fetch(`http://localhost:3000/api/building/all?skip=${pageOffset}&limit=${pageSize}`);
const responseJson = await response.json();
return responseJson.buildings;
} catch(error){
console.error(error);
}
async function fetchData (url, { type = 'json' } = {}) {
return await (await fetch(url))[type]();
}
// Example:
(async () => {
console.log(await fetchData('http://canskit.com', { type: 'text' }));
})();
As the original js on ES7, not aim at react-native

How to use AsyncStorage.setItem in fetch callback?

I got syntax error in my code.
async getJSON() {
await fetch(url)
.then((response) => response.text())
.then((responseText) => {
await AsyncStorage.setItem(STORAGE_KEY, responseText);
})
.catch((error) => {
console.warn(error);
});
},
Error is Unexpected token on await AsyncStorage.setItem(STORAGE_KEY, responseText);
I guess it's complaining await
For every await you need an async.
async getJSON() {
await fetch(url)
.then((response) => response.text())
.then(async (responseText) => { // <-- add async here
await AsyncStorage.setItem(STORAGE_KEY, responseText);
})
.catch((error) => {
console.warn(error);
});
},
Also... the point of async/await is to make the code look sync when is actually async. You can rewrite the above code like this:
async getJSON() {
try {
var response = await fetch(url);
var responseText = response.text();
await AsyncStorage.setItem(STORAGE_KEY, responseText);
} catch(error) {
console.warn(error);
}
}

Categories