Tengo una aplicación Vue. Me gustaría recuperar entradas (de una base de datos) basadas en un ID de usuario. Tengo los siguientes métodos en Vue:
export default { name: 'Entries', data() { return { userid: null }; }, methods: { getEntries() { this.getUserID(); console.log("userid getEntries: " + this.userid); axios.get('/entries', this.userid) .then((res) => { this.entries = res.data; console.log(this.entries); }) .catch((error) => { console.error(error); }); }, getUserID() { axios.get('/userid') .then((res) => { this.userid = res.data; console.log("userid getUserId: " + this.userid ); }) .catch((error) => { console.error(error); }); }, }, created() { this.getEntries(); } }; Dentro del método getEntries , estoy llamando inmediatamente a la función getUserID . Asumiría que esto establece la variable ID de userid en el valor recuperado del método getUserID .
En cambio, obtengo el siguiente resultado en la consola del navegador, exactamente en este orden:
userid getEntries: null userid getUserId: user_a ¿Por qué imprime primero la salida de la consola desde la función getEntries ? ¿Y por qué es nulo si primero ejecuta el método getUserID ?
¿Cómo podría cambiar para que las /entries llamadas de axios puedan pasar el ID de usuario?
Las llamadas axios son asíncronas, si necesita que se complete el ID de usuario antes de que se llame a cualquier otra cosa, entonces debe completar antes de que se llame a cualquier otra cosa, en montado/creado.
Entonces puedes reaccionar a su cambio con un observador. Podría llamar a getEntries cuando la llamada getUserID se resuelva, pero está sucia y combina los dos métodos.
Y no olvide asignar entries en data.
Esto funcionará:
export default { name: 'Entries', data() { return { userid: null, entries: [] }; }, watch: { userid (v) { if (v) this.getEntries() } }, mounted() { this.$nextTick(this.getUserID) }, methods: { getEntries() { console.log("userid getEntries: " + this.userid); axios.get('/entries', this.userid) .then((res) => { this.entries = res.data; console.log(this.entries); }) .catch((error) => { console.error(error); }); }, getUserID() { axios.get('/userid') .then((res) => { this.userid = res.data; console.log("userid getUserId: " + this.userid); }) .catch((error) => { console.error(error); }); } } };Usando asíncrono/espera
export default { name: 'Entries', data() { return { userid: null, entries: [] }; }, watch: { userid (v) { if (v) this.getEntries() } }, mounted() { this.$nextTick(this.getUserID) }, methods: { async getEntries() { try { const { data } = await axios.get('/entries', this.userid) this.entries = data; } catch (error) { console.error(error); } }, async getUserID() { try { const { data } = await axios.get('/userid') this.userid = data; } catch (error) { console.error(error); } } } };Dado que getUserId es asíncrono, no regresa de inmediato. Por lo tanto, debe esperar a que regrese antes de continuar. Esto se puede hacer usando then , pero las Promesas anidadas son un poco desagradables para trabajar. Una opción más simple es usar async/await en su lugar:
async getEntries() { await this.getUserID(); console.log("userid getEntries: " + this.userid); axios.get('/entries', this.userid) .then((res) => { this.entries = res.data; console.log(this.entries); }) .catch((error) => { console.error(error); }); },