1

I have a button that makes an http.get on click, and then displays some data, although my async/awaits seem to not be synchronized correctly.

For a reason I haven't quite figured out yet, this.tabRows = file.contents will be called before loadDateFolderFileContents() completes. Am I missing an await somewhere?

 async ngAfterViewInit() { if (!this.drawn) { if(!file.contents){ await this.dataLakeService.loadDateFolderFileContents(file.parentFolder); } this.tabRows = file.contents; this.redraw(); } } public async loadDateFolderFileContents(dateFolder: folder) { await date.files.map(async file => { file.contents = await this.getFileContents(dateFolder.name, file.name); }); } public async loadDateFolderFileContents(dateName: string, fileName: string): Promise<any> { var url = this.buildUrl(dateName, fileName); var fileContents = {}; await this.http.get<any>(url).toPromise() .then(contents => { fileContents = contents; }) .catch(e => { console.log(`Error retreiving file contents from url ${url}. Exception:${e}`); }); return fileContents; } 
3
  • 1
    This: return fileContents; --> Does this answer your question? How do I return the response from an asynchronous call? Commented Jan 25, 2021 at 22:19
  • 2
    this is weird, you are awaiting, but you have a .then which won't be waited for. just let content = await this.http.get .... and put it in a try catch Commented Jan 25, 2021 at 22:20
  • @KeithNicholas Thanks for the tip. I'm still new to the whole world of JS/TS + Promises, so I'm still struggling with them here and there. Commented Jan 26, 2021 at 0:44

3 Answers 3

1

If you use await in a map, map will always return an array of promise. This is because asynchronous functions always return promises.
Since map always return promises (if you use await), you have to wait for the array of promises to get resolved. You can do this with await Promise.all(arrayOfPromises), after all promises are resolved, Promise.all returns a single promise.
below is your updated code

async ngAfterViewInit() { if (!this.drawn) { if(!file.contents){ await this.dataLakeService.loadDateFolderFileContents(file.parentFolder); } this.tabRows = file.contents; this.redraw(); } } public async loadDateFolderFileContents(dateFolder: folder) { await Promise.all(date.files.map(async file => { file.contents = await this.getFileContents(dateFolder.name, file.name); })); } public async loadDateFolderFileContents(dateName: string, fileName: string): Promise<any> { var url = this.buildUrl(dateName, fileName); var fileContents = {}; await this.http.get<any>(url).toPromise() .then(contents => { fileContents = contents; }) .catch(e => { console.log(`Error retreiving file contents from url ${url}. Exception:${e}`); }); return fileContents; } 
Sign up to request clarification or add additional context in comments.

4 Comments

am I required to return from the loadDateFolderFileContents()?
@ChrisPhillips, It's your choice, shouldn't matter because async function returns it's own undefined value wrapped in promise, if you don't return anything from it, otherwise whatever you are returning and here we are already using await inside the async function, so function will only return after asynchronous task is done
@ChrisPhillips let me know if it works or not
Thanks, this was the correct answer (as were some others below!). I'd have marked it sooner but I was heading out for the evening.
1

map is not async so instead of:

await date.files.map(async file => { ... 

try

await Promise.all(date.files.map(async file => { ...) 

Comments

1

I think this is what you are trying to do:

async ngAfterViewInit() { if (!this.drawn) { if(!file.contents){ await this.dataLakeService.loadDateFolderFileContents(file.parentFolder); } this.tabRows = file.contents; this.redraw(); } } public async loadDateFolderFileContents(dateFolder: folder) { await Promise.allSettled(date.files.map(async file => { file.contents = await this.getFileContents(dateFolder.name, file.name); return file; })); } public async loadDateFolderFileContents(dateName: string, fileName: string): Promise<any> { var url = this.buildUrl(dateName, fileName); var fileContents = {}; try { const contents = await this.http.get<any>(url).toPromise(); fileContents = contents; return fileContents; } catch(e){ console.log(`Error retreiving file contents from url ${url}. Exception:${e}`); } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.