I have an es6 class, with an init()
method responsible for fetching data, transforming it, then update the class's property this.data
with newly transformed data.
So far so good.
The class itself has another getPostById()
method, to just do what it sounds like. Here is the code for the class:
class Posts {
constructor(url) {
this.ready = false
this.data = {}
this.url = url
}
async init() {
try {
let res = await fetch( this.url )
if (res.ok) {
let data = await res.json()
// Do bunch of transformation stuff here
this.data = data
this.ready = true
return data
}
}
catch (e) {
console.log(e)
}
}
getPostById(id){
return this.data.find( p => p.id === id )
}
}
Straightforward, except I have an async/await
mechanism in the init()
method.
Now, this code will work correctly:
let allPosts = new Posts('https://jsonplaceholder.typicode.com/posts')
allPosts.init()
.then( d => console.log(allPosts.getPostById(4)) )
// resulting Object correctly logged in console
but it only gets printed into the console:
How could I use allPosts.getPostById(4)
as a return
of a function ?
Like:
let myFunc = async () => {
const postId = 4
await allPosts.init() // I need to wait for this to finish before returning
// This is logging correct value
console.log( 'logging: ' + JSON.stringify(allPosts.getPostById( postId ), null, 4) )
// How can I return the RESULT of allPosts.getPostById( postId ) ???
return allPosts.getPostById( postId )
}
myFunc()
returns a Promise
but not the final value. I have read several related posts on the subject but they all give example of logging, never returning.
Here is a fiddle that includes two ways of handling init()
: using Promise
and using async/await
. No matter what I try, I can't manage to USE the FINAL VALUE of getPostById(id)
.
The question of this post is: how can I create a function that will RETURN the VALUE of getPostById(id)
?
EDIT:
A lot of good answers trying to explain what Promises are in regards to the main execution loop. After a lot of videos and other good reads, here is what I understand now:
my function init()
correctly returns. However, within the main event loop: it returns a Promise, then it is my job to catch the result of this Promise from within a kinda parallel loop (not a new real thread). In order to catch the result from the parallel loop there are two ways:
use
.then( value => doSomethingWithMy(value) )
use
let value = await myAsyncFn()
. Now here is the foolish hiccup:
await can only be used within an
async
function :p
thus itself returning a Promise, usable with await
which should be embed in an async
function, which will be usable with await
etc...
This means we cannot really WAIT for a Promise: instead we should catch parallel loop indefinitely: using .then()
or async/await
.
Thanks for the help !