Clearner Way To Wait For Function To Complete Before Continuing
First I fetch a random quote from a public api. Only AFTER I actually have a quote I want to render the page including that quote.
I am a JavaScript newbie so please bear with me if this is a stupid question.
I was struggling with waiting for the api call to return BEFORE continuing with rendering the page.
I wanted to do the following, but this doesn't work because res.render
will be called before I have a quote. (note: I am using Express and Axios)
async function getRandomQuote() {
try {
const res = await axios.get("https://api.quotable.io/random?tags=famous-quotes")
console.log(`${res.data.content} - ${res.data.author}`) //This prints fine
return res.data
} catch(e) {
console.log('error', e)
}
}
app.get('/', (req, res) => {
const quote = getRandomQuote()
console.log(`${quote.content} - ${quote.author}`) //This prints 'undefined' because 'getRandomQuote' isn't finished yet
res.render('home', { quote })
})
The only way I figured out to do it is as follows, but I find this really messy. Is there a cleaner way to do this? Or do I always need to put all the lines of code that I want to wait for each other in an async function?
async function getRandomQuote() {
try {
const res = await axios.get("https://api.quotable.io/random?tags=famous-quotes")
console.log(`${res.data.content} - ${res.data.author}`) //This prints fine
return res.data
} catch(e) {
console.log('error', e)
}
}
app.get('/', (req, res) => {
const getQuoteAndRender = async() => {
const quote = await getRandomQuote()
console.log(`${quote.content} - ${quote.author}`) //This prints only if I wrap everything in yet another aync function, otherwise it will not wait for 'getRandomQuote' to complete
res.render('home', { quote })
}
getQuoteAndRender()
})
(Note: I realize rendering the page after I successfully get a quote is not ideal either because this means I will not get a page at all if the quote api (for some reason) doesn't work. But for now I just want to know how to do this with the waiting.)
Answer
Heres what you need to do. Make your controller async
by doing this app.get('/', async (req, res)
app.get('/', async (req, res) => {
const quote = await getRandomQuote()
console.log(`${quote.content} - ${quote.author}`) //This prints 'undefined' because 'getRandomQuote' isn't finished yet
res.render('home', { quote })
})
Related Questions
- → How to update data attribute on Ajax complete
- → October CMS - Radio Button Ajax Click Twice in a Row Causes Content to disappear
- → Octobercms Component Unique id (Twig & Javascript)
- → Passing a JS var from AJAX response to Twig
- → Laravel {!! Form::open() !!} doesn't work within AngularJS
- → DropzoneJS & Laravel - Output form validation errors
- → Import statement and Babel
- → Uncaught TypeError: Cannot read property '__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED' of undefined
- → React-router: Passing props to children
- → ListView.DataSource looping data for React Native
- → Can't test submit handler in React component
- → React + Flux - How to avoid global variable
- → Webpack, React & Babel, not rendering DOM