catching errors in typescript promises

31,417

Solution 1

One way to chain promises is to return a promise inside then function, like this:

method1()
  .then(response1 => {
    // ... do something
    return method2(response1);
  })
  .then(response2 => {
    // ... do something
    return method3(response3);
  })
  .catch(error => handleError(error))
  .finally(() => handleFinally())

When all promises are successfully resolved, as expected, all methods are called sequentially (method1 -> method2 -> method3 -> handleFinally).

When one promise fails, all subsequent are skipped and catch is invoked instead. Supposing method2 fails, we have this chain of calls: method1 -> method2 -> handleError -> handleFinally.

Now suppose we want to ignore the error in method2, we can add a catch statement for this call:

method1()
  .then(response1 => {
    // ... do something
    return method2(response1)
      .catch(error2 => silentlyHandleError(error2));
  })
  .then(response2 => {
    // ... do something
    return method3(response3);
  })
  .catch(error => handleError(error))
  .finally(() => handleFinally())

Notice that the catch must not be placed among the main chain of promises. The next block explains a little bit more:

method1()
  .then(response1 => {
    // ... do something
    return method2(response1);
  })
  .catch(error => silentlyHandleError(error)) // catchs error1 and error2
  .then(response2 => {
    // ... do something
    return method3(response3);
  })
  .catch(error => handleError(error))
  .finally(() => handleFinally())

Solution 2

Have each promise return the nested promise, and the top promise have a .catch(..)

Share:
31,417
rubmz
Author by

rubmz

Updated on November 03, 2020

Comments

  • rubmz
    rubmz over 3 years

    Angular2 has very useful promises error catching mechanism for chained promises. Yet, the usual case (at least for me) is that of promises called from within the resolve handler of the previous one. This is due to the need to process information prior to starting the next promise. For example:

    this.d( "facebookOAuthLogin() - starts" );
    this.fbProvider.login().then(
        ( loginResponse: { status: string, authResponse: any, accessToken: string, expiresIn: string, session_key: string, sig: string, userID: string } ) =>
        {
            this.d( "facebookOAuthLogin() - fbProvider.login() succeeded" );
            Config.config.sessionToken = loginResponse.authResponse.accessToken;
            this.fbProvider.getCurrentUserProfile().then(
                ( profileData : { email: string, name: string } ) =>
                {
                    this.d( "facebookOAuthLogin() - fbProvider.getCurrentUserProfile() succeeded" );
                    Config.config.user_email = profileData.email;
                    Config.config.user_name = profileData.name;
                    this.fbProvider.getUserPicture().then(
                        ( pictureData : { data:{ is_silhouette: boolean, url: string, width: number, height: number } } ) =>
                            {
                                this.d( "facebookOAuthLogin() - fbProvider.getUserPicture() succeeded" );
                                // this.facebook_picture_url = pictureData.data.url;
                                // this.facebook_picture_is_silhouette = pictureData.data.is_silhouette;
                                if( pictureData.data.is_silhouette || pictureData.data.url == null )
                                {
                                    this.d( "facebookOAuthLogin() - pictureData.data.url == null" );
                                    Config.config.jpegBase64Data = null;
                                    this.afterFacebookLogin();
                                }
                                else
                                {
                                    this.d( "facebookOAuthLogin() - pictureData.data.url != null" );
                                    ImageStore.readToData( pictureData.data.url ).then(
                                        dataBase64 =>
                                        {
                                            this.d( "facebookOAuthLogin() - facebook picture read successfully" );
    

    So, the question is - If I want to catch all the errors in all the handlers in the simplest way (let's leave out the type of the exceptions - Assume I just need to log the error and report. Any error - Without handling them separatedly.)

    From what I understand putting a try{}catch(err) around the code would not catch the errors thrown from the Promise handler.

    With the code above - Do I need to add a try/catch in every Promise handler, or can I use the external (first) promise's .catch() method?