Reputation: 2134
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;
}
Upvotes: 1
Views: 135
Reputation: 1503
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;
}
Upvotes: 1
Reputation: 182
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}`);
}
}
Upvotes: 1
Reputation: 2880
map is not async so instead of:
await date.files.map(async file => {
...
try
await Promise.all(date.files.map(async file => {
...)
Upvotes: 1