Zag Gol
Zag Gol

Reputation: 1076

Typescript - Promise returns to early

I'm given a code with 3 parts that must not be changed:

1. a call to getData function, and then prints the output.

getData().then(console.log); 

2. The function signeture:

async getData(): Promise<string[]>

3. function getDataFromUrl

function getDataFromUrl(url: string, callback: any) {
   fetch(URL)
   .then((content: any) => content.json())
   .then((data) => callback(data));
}

This is my implementation for getData function:

async getData(): Promise<string[]> {  
  return await new Promise<any>(function(resolve, reject) {
    resolve(getDataFromUrl(myUrl, ((data: string[]): string[]=> { 
      return data
    })))
  }); 
} 

The problem is that the code after fetch, runs after

getData().then(console.log);

so console.log prints: undefined

What do I need to change in the getData function?

Thanks

Upvotes: 0

Views: 576

Answers (3)

ziaahsan
ziaahsan

Reputation: 34

function getDataFromUrl(url, f) {
  // call fetch (returns promise) but we can use then as well.
  // note our callback: f where we pass the data to the callback.
  fetch(url).then((content) => content.json()).then(data => f(data));
}

// edit: note we don't need this be async anymore...
async function getData() {
  // create a promise...
  return new Promise((resolve, reject) => {
    // we call with callback arrow and resolve data here
    getDataFromUrl('https://randomuser.me/api/', (data) => resolve(data));
  })
}

// we print the data once the getData is done fetching
// you can also use reject to handle anything that goes wrong in above.
getData().then(data => console.log(data));

Resources used:

  • Fetch API
  • Async, Await, and Promise
  • Callback

Upvotes: -1

Emiel Zuurbier
Emiel Zuurbier

Reputation: 20924

Instead of resolving the getDataFromUrl function, you should resolve the value that the callback function exposes.

getData(): Promise<string[]> {  
  return new Promise<string[]>(function(resolve, reject) {
    getDataFromUrl(myUrl, (data: string[]): string[] => { 
      resolve(data)
    })
  }); 
} 

It's unfortunate you can't change anything about the other functions, because returning the promise created by fetch in your getDataFromUrl function, would make the code way better, as Quentin demonstrates.

Upvotes: 2

Quentin
Quentin

Reputation: 943142

getDataFromUrl doesn't have a return value, so it returns undefined.

So you pass undefined to resolve (which resolves your other promise) and then, later the promise created by getDataFromUrl (or rather fetch) resolves.


  • Don't create bonus promises
  • Don't mix callbacks and promises

Just return the promise from fetch.

function getDataFromUrl(url: string, callback: any) {
   return fetch(URL)
   .then((content: any) => content.json());
}

And use that promise instead of creating a new one in getData (which doesn't need to use await because that will just resolve the promise which will immediately get wrapped in a new promise by async.

getData(): Promise<string[]> {  
    return getDataFromUrl(myUrl);
}

Upvotes: 1

Related Questions