I have a function that displays a pop up window, the windows appears after a few seconds of delay, I found that if I remove the function this.service.GetAllItems()
the windows will appear immediately, therefore I am trying to edit the function to run regardless of GetAllItems()
server time response.
The functions are:
await this.service.GetAllItems(e.show).then(async Oldest => {
this.service.GetItemId(e.showID).subscribe(x => {
let a = x;
this.dialog.closeAll();
return this.dialog.open(InformationComponent, {
data: { name: a, All: ShowAll, lang: this.TheLang }
, panelClass: 'custom-dialog-container'
});
});
});
and
async GetAllItems(e: any) {
try {
const response = await this.http.get<Items[]>(this.baseUrl 'Items/GetWell=' e.toString()).toPromise();
return response;
} catch (err) {
console.log(err);
}
}
The problem is that it simply doesn't work. Pop up will appear after a delay even though GetAllItems()
is asynchronous. How can I modify the code to run asynchronously?
CodePudding user response:
It looks like the problem is caused by the fact that you are first getting all the data with GetAllItems(e.show) and inside that function you are waiting for data, since it's async the function return after few seconds because it wait for the data, and only after it opens the dialog (caused by the .then that is performed after the function is finished) The code needs some reorder of action but I can't do it right now since I'm going to sleep sorry, I think you should first open the dialog and the call GetAllItems(), I used dialogs in my project but I've never used them in a return, you can do something like this to open them before the function finishes
let dialogRef = this.dialog.open(InputDialogComponent, {
// code
})
I don't know what you are doing inside the dialog but if you want to check for like a "cancel" button you can do something like this
dialogRef.afterClosed().subscribe(result => {
if (result === "false") {
return
}
//code
})
And this is the cancel button in the dialog
<button mat-dialog-close mat-dialog-close="false">Cancel</button>
The data inside the dialog should update automatically using asyncs functions
CodePudding user response:
It makes me wonder why are you using a mix of promises with observables
rather than just observables
? The http
module returns an observable by default, and Angular
along with Angular Material
uses heavily observables in general.
Also, given your code example, is confusing what's the purpose of getAllItems()
, that function returns a response, but you are not even using it from my perspective.
Since you need to handle multiple observables
at the same time, you can make use of rxjs
operators for flattening these observables
such as mergeMap
, switchMap
, exhaustMap
and concatMap
depending of the situation.
Based on what you posted, try making these changes:
service
getAllItems(e: any): Observable<Items[]> {
return this.http.get<Items[]>(this.baseUrl 'Items/GetWell=' e.toString()).pipe(
catchError((error) => {
console.log('Error: ', error);
return EMPTY; // provided by RxJs
})
)
}
this.service.getAllItems(e.show).pipe(
// here you are not using "oldest"... why bother then?
mergeMap((oldest) => this.service.getItemId(e.showId).pipe(
mergeMap(response => {
this.dialog.closeAll();
const data = this.getData(response);
return this.dialog
.open(InformationComponent, { data, panelClass: 'custom-dialog-container'})
.afterClosed();
})
)
)
).subscribe((dialogResponse) => {
if (dialogResponse) {
//... the dialog was closed, and you do something with the response
}
});
private getData(name) {
return {
name,
all: showAll,
lang: this.theLang
}
}
Additionally, the naming convention for functions, variables, object properties in javascript/typescript is camelCase
, don't use upper case, makes your code hard to read.
For more information about observables
, take a look at the official docs