问题
Disclaimer: This is a "good programming practices" question rather than a "fix my broken code" question.
Environment
Angular 5.2.9, Angular Material 5.2.4, Typescript 2.4.2, Rxjs 5.5.8
Issue
I am using the mat-dialog component of the angular material library, and subscribing to the observable returned from afterClosed(). Inside of that subscription I have a simple if statement. If value is returned, return value, otherwise return null. My tslint is throwing a fit about returning from inside the async subscription. The exact error is, "TS2355: A function whose declared type is neither 'void' nor 'any' must return a value."
Code
private openModal() : string {
// some setup code
this.dialog.open(MyModalComponent, configModal)
.afterClosed()
.subscribe(( data : string ) => {
if ( data ) {
return data;
} else {
return null;
}
});
// cant put return here, this will execute before modal returns data
}
Question
I want to specify a return type 'string' to my function, but that means I need to do the actual return from within the synchronous function openModal(), and not the async code inside the subscription. I am open to all suggestions on how to improve this code. Thanks!
回答1:
Actually, your code is kind of broken and this is not only about good programming practices.
You are using an Observable, that makes your code asynchronous. Once your code is asynchronous, it will never become synchronous again and you have to use asynchronous types until the very last consumer of your function. In an Angular application this is usually a Component or Directive.
This is a core concept of JavaScript and is most prominently applied with Observables, Promises and Callback Functions. It is vital to understand how asynchronous code execution and the JavaScript event loop works in order to work with this programming language.
As for your code example, you need to change the return type of your function to Observable<string>
and pass the observable on to your component class where you can assign it to a property and let Angular handle the rest.
It looks like this:
private openModal() : Observable<string> {
// some setup code
return this.dialog.open(MyModalComponent, configModal)
.afterClosed();
}
Then in your component...
private data: string;
clickSomeButton() {
this.openModal().subscribe(data => this.data = data);
}
来源:https://stackoverflow.com/questions/52506013/what-is-the-proper-way-to-return-from-within-an-angular-subscription