Search code examples
javascriptasync-awaites6-promise

Using async await in map with a join


I am using vanilla js to create a spa and I have hit an issue with using async-await with maps. My page is like this;

render: async () => {
    let result = await getPostsList()
    if (result.status == "success") {
        let posts = result.data
        let view =  /*html*/`
        <section class="section pageEntry">
            <h1> Home </h1>

            <div class="columns is-multiline" id="cards_container">
            ${await Promise.all(posts.map( (post) => Card.render(post)).join('\n ')) }
            </div>
        </section>
        `
        return view
    } else {
        console.log(result)
    }

and the child component is;

 render: async (post) => {
        // console.log(post)
        let view =  /*html*/`                
            <div class="column is-half">
                <article class="media">
                    <figure class="media-left">
                        <p class="image is-128x128">
                        <img src="https://bulma.io/images/placeholders/128x128.png">
                        </p>
                    </figure>
                    <div class="media-content">
                        <div class="content">
                        <p>
                            ${post.title}
                            <strong>${post.author}</strong> <small>@johnsmith</small> <small>31m</small>
                            <br>
                            ${post.content}
                        </p>
                        </div>
                    </div>      
                </article>
            </div>
        `
        return view

I understand that to use async-await with map, i should use a Promise.all. However, on doing that i get commas between my individual components. enter image description here

If I use a .join('') to remove the commas, it is then giving me a completely weird output. If I try join with async-await in maps, I get something like

enter image description here


Solution

  •   await a().b()
    

    awaits the result of the b property call.

     (await a()).b()
    

    awaits a and then calls b() on the result. Additionally you call join directly on the array of promises:

    posts.map( (post) => Card.render(post)).join('\n ')
    

    You want to call it on the awaited result. All in all:

     const rendered = await Promise.all(posts.map( (post) => Card.render(post));
    
     return `... ${rendered.join("\n")} ...`