Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Async / Await Try Catch Error Handling

I'm using the JSONPlaceholder API: https://jsonplaceholder.typicode.com. I have the following in my service.ts:

public async getPosts(): Promise<Post[]> {
    try {
        const response = await this._http.get<Post[]>(this._baseUrl + "api/JsonPlaceholder/GetPosts");
        return response.toPromise();
    } catch (error) {
        await this.handleError(error);
    }
}

Which I try to use in my component.ts:

public posts: Post[];

public async ngOnInit() {
    const posts = await this._placeholderService.getPosts();
    this.posts = posts;
}

However, the TypeScript compiler throws an error on public async getPosts(): Promise<Post[]> - Function lacks ending return statement and return type does not include 'undefined'.

It is expecting a return statement in either the catch block or outside the try-catch. What is best practice for handling errors like this when I want to return a specific type...in my case Post[]. Is there a better way to structure these types of calls?

like image 520
Ryan Buening Avatar asked Dec 08 '22 16:12

Ryan Buening


2 Answers

What does handleError do? What do you want to happen when the http request fails? Right now you are swallowing the error and returning undefined. You could fix your return type annotation as Promise<Post[] | undefined> (or remove it which will infer that type), then you need to handle the undefined case in upstream code:

public async ngOnInit() {
    const posts = await this._placeholderService.getPosts();
    if (posts) {
        this.posts = posts;
    } else {
        this.errorMessage = "Failed to load posts!";
    }
}

Or you could just return [] if you aren't handling the error case anyway:

} catch (error) {
    await this.handleError(error);
    return [];
}

Or you could throw the error and allow upstream code to handle it or not:

} catch (error) {
    await this.handleError(error);
    throw error;
}

public async ngOnInit() {
    try {
        const posts = await this._placeholderService.getPosts();
        this.posts = posts;
    } catch(error) {
        // Note that 'error' could be almost anything: http error, parsing error, type error in getPosts(), handling error in above code
        this.errorMessage = "Failed to load posts!";
    }
}
like image 141
Aaron Beall Avatar answered Dec 10 '22 11:12

Aaron Beall


It is expecting a return statement in either the catch block or outside the try-catch. What is best practice for handling errors like this when I want to return a specific type...in my case Post[]. Is there a better way to structure these types of calls?

Simple annotation to reflect the true nature of the code you have written:

public async getPosts(): Promise<Post[] | undefined> { // notice `undefined`
    try {
        const response = await this._http.get<Post[]>(this._baseUrl + "api/JsonPlaceholder/GetPosts");
        return response.toPromise();
    } catch (error) {
        await this.handleError(error);
    }
}

TypeScript is just pointing out this truth for you 🌹

like image 20
basarat Avatar answered Dec 10 '22 12:12

basarat