2
<!DOCTYPE html>
<html>
    <head>
        <title>Async/Await</title>
    </head>
    <body>
        <button id="getData">getData</button>
    <script>
        document.getElementById("getData").addEventListener("click", getAll);
        function displayData(){
            return new Promise((res, rej)=>{
                fetch("https://jsonplaceholder.typicode.com/posts").then((res)=>{
                    return res.json();
                }).then((data)=>{
                    console.log(data);
                }).catch((err)=>{
                    rej(err);
                });
                fetch("https://jsonplaceholder.typicode.com/users").then((res)=>{
                    return res.json();
                }).then((res)=>{
                    console.log(res);
                }).catch((err)=>{
                    rej(err);
                })
                res();
            });
        }

        function getmoreData(){
            fetch("https://reqres.in/api/users/2").then((res)=>{
                return res.json();
            }).then((data)=>{
                console.log(data.data);
            }).catch((err)=>{
                console.log(err);
            });
        }

        async function getAll(){
            await displayData();
            getmoreData();
        }
    </script>
    </body>
</html>

I want to call two APIs at the same time which is in display function and after getting those data, I want to call another API which is in getmoreData function. That's why I used promises and async await but when I click button then getmoreData execute first and then I get data of those two APIs which is in displayData function. Is there something wrong in my code and if not then why I am not getting desired result.

Ayaz
  • 41
  • 3
  • 1
    Avoid the [`Promise` constructor antipattern](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it)! – Bergi Feb 01 '20 at 16:07

2 Answers2

3

The problem is that you're resolving the promise that you return from displayData before the fetch responses come in.

To fix that, you can skip the building of a new Promise and use Promise.all. Here is an example:

function displayData(){
    const call1 = fetch("https://jsonplaceholder.typicode.com/posts").then((res)=>{
        return res.json();
    }).then((data)=>{
        console.log(data);
        return data;
    });
    const call2 = fetch("https://jsonplaceholder.typicode.com/users").then((res)=>{
        return res.json();
    }).then((res)=>{
        console.log(res);
        return res;
    });
    return Promise.all([call1, call2]);
}

Also, you have some repeating code, you can refactor this to:

function getAndPrintData(url) {
  return fetch(url)
    .then(rsp => rsp.json())
    .then(json => {
      console.log(json);
      return json;
    });
}

const base = "https://jsonplaceholder.typicode.com/";
const urls = [`${base}posts`, `${base}users`];

function displayData() {
  return PromiseAll(urls.map(getAndPrintData));
}
Titus
  • 22,031
  • 1
  • 23
  • 33
  • Yes, You are right. I was resolving the promise before data was getting fetched. It also works if we resolve it inside then. I just tried. But your approach of using promise.all is nice and clean and yeah second approach is helpful too. – Ayaz Feb 01 '20 at 16:29
  • @MohdAyazurRahmanShaikh Because both promises run at the same time, resolving the created promise in one of the `.then` callbacks only assures that one fetch is done not both of them. The promise returned by `Promise.all` resolves when both calls are done. – Titus Feb 01 '20 at 16:37
1

Optionally you could make the second function to be a call back when the first resolve:

async function getAll(){
    await displayData().then( () => getmoreData() )
}
Addis
  • 2,480
  • 2
  • 13
  • 21