Utilizing Angular's promise rejection chaining method

When dealing with a chained promise and facing rejection in any of the promises, I require an async operation to be performed (such as retrieving a translated error message). Since chaining on rejection seems impossible when there is already a chained promise on success, I tried nesting the async calls. However, I encountered an issue where I am not receiving the resolved promise back from

deferred.reject(deferredRejection.promise);
below. Any guidance would be greatly appreciated!

login: function(email, password) {
  var deferred = $q.defer();
  AuthService.login(email, password).then(function(response) {
    var user = {
      'accountToken': response.accountToken,
      'email': response.username,
      'onboarded': response.onboarded,
      'verified': response.verified
    };          
    return SyncStorageService.write(SyncStorageService.storageKeys.user, 
        user);  
  }, function(error) {
    // login failed
    var deferredRejection = $q.defer();
    $translate('ALERTS.LOGIN_FAILED').then(function(translatedValue) {
      deferredRejection.resolve(translatedValue);
    });
    deferred.reject(deferredRejection.promise);
  }).then(function(data) {
    deferred.resolve(data);
  }, function(error) {
    // saving data failed
    var deferredRejection = $q.defer();
    $translate('ALERTS.UNKNOWN').then(function(translatedValue) {
      deferredRejection.resolve(translatedValue);
    });
    deferred.reject(deferredRejection.promise);
  });
  return deferred.promise;
}

Updated Solution:

Following the advice provided, I have refactored the code as shown below:

login: function(email, password) {
  return AuthService.login(email, password).then(function(response) {
    return {
      'accountToken': response.accountToken,
      'email': response.username,
      'onboarded': response.onboarded,
      'verified': response.verified
    };
  }).then(function(data) {
    return SyncStorageService.write(SyncStorageService.storageKeys.user, 
        data);
  });
}

Additional Information:

  • Both AuthService.login and SyncStorageService.write now reject promises with an Error object (e.g.
    new Error('ALERT.ERROR_MESSAGE');
    ), which will propagate through the login method to the controller (instead of handling translation at the service level)
  • The calling controller for the login method includes .then() and .catch() blocks - if caught in a .catch(), the Error.message passed will be translated and displayed.

Answer №1

It seems like you're not effectively chaining promises and could be falling into the trap of using the forgotten promise/deferred anti-pattern. By making some assumptions about your intended behavior and simplifying the calls to $translate, the code below might align more with what you're aiming for:

login: function(email, password) {
  return AuthService.login(email, password).then(function(response) {
    return {
      'accountToken': response.accountToken,
      'email': response.username,
      'onboarded': response.onboarded,
      'verified': response.verified
    };          
  }, function() {
    return $q.reject('ALERTS.LOGIN_FAILED');
  }).then(function(user) {
    return SyncStorageService.write(SyncStorageService.storageKeys.user, user).catch(function() {
      return $q.reject('ALERTS.UNKNOWN');
    });
  }).catch(function(message) {
    return $translate(message).then(function(translatedValue) {
      return $q.reject(translatedValue);
    });
  });
}

Key points to remember are:

  • If you specifically want to reject the derived promise, use $q.reject(error) in the success or error callback.

    All error callbacks in the example follow this pattern. The translations keys used as errors will eventually propagate through to the final catch callback. The success callback from $translate also rejects its resolved promise, so the final catch callback returns a rejected promise, likely displaying the translated error to the user.

  • If you want to resolve the derived promise, return any value that isn't a promise in the success or error callbacks. This returned value will resolve the derived promise (including undefined if no explicit return is provided).

    This is demonstrated when returning the user object return {'accountToken'.... in the first callback.

  • To delay resolution or rejection of a promise, return another promise in the success or error callback. The derived promise will wait for this nested promise's outcome before resolving or rejecting accordingly.

    This concept is shown in the code by returning SyncStorageService.write... and $translate(....

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Missing Cookie in request using NodeJS and NextJS

Struggling with integrating cookies in a fullstack app I'm developing using Node for backend and NextJS for frontend on separate servers. The challenge lies in getting the browser to attach the cookie received in the response header from the node serv ...

What steps can be taken to customize this code in order to develop a dictation application?

Currently, I have a code that functions by comparing two strings: str2 (which represents user input) and str1 (our reference string). The purpose is to determine whether any words in str2 are spelled correctly or incorrectly. So far, the code works well. H ...

Utilizing jQuery to efficiently chunk JSON data through AJAX calls

Is there a way to efficiently handle the retrieval of large amounts of JSON data through an ajax request? I am looking for a jQuery or JavaScript function that can assist with "chunking" the data. For example, I would like the ability to continuously rece ...

How can I ensure security measures are in place to avoid XSS attacks on user-generated HTML content?

Currently, I am in the process of developing a web application that will allow users to upload entire web pages onto my platform. My initial thought was to utilize HTML Purifier from http://htmlpurifier.org/, but I am hesitant because this tool alters the ...

Is it necessary for me to use a .jsx extension when saving my React component files?

After working with React for a few months, I recently noticed that some of my files have the .js extension while others have the .jsx extension. Surprisingly, when I write JSX code in the .js files, everything still functions correctly. Is there any signif ...

Using jQuery to load the center HTML element

So here's the plan: I wanted to create a simple static website with responsive images that load based on the browser width. I followed some suggestions from this link, but unfortunately, it didn't work for me. I tried all the answers and even a ...

I encountered an error while trying to load the resource from http://premieroptie.nl/wp-content/themes/theme51771/favicon.ico: net::ERR_NAME_NOT_RESOLVED

Upon opening my website URL, computertechnet.nl, I noticed an error when inspecting and checking the console tab. The specific error message is: Failed to load resource: net::ERR_NAME_NOT_RESOLVED for . In addition, a second warning was displayed: G ...

Extract the comma-separated values from an array that are combined as one

please take a look at this dropdown In my array list displayed as ng-option, some values come as PCBUs separated by commas. For example, in the JSON response, the value of the first PCBU is "NKSMO,NNOWR". I am attempting to display these as two separate P ...

What is the best way to save longitude and latitude coordinates in a database using the <input> method?

Learn how to use HTML code <html> <body> <p>Press the button below to receive your coordinates.</p> <button onclick="getLocation()">Get Coordinates</button> <p id="demo"></p> <script> var x = doc ...

Ways to determine the name of the calling function in an AJAX or XMLHttpRequest request?

I am currently exploring ways to programmatically identify the function name responsible for triggering an Ajax call in JavaScript or jQuery within an existing codebase. As I delve into instrumenting a large existing codebase, I am seeking to pinpoint the ...

Insufficient Resources Error (net::ERR_INSUFFICIENT_RESOURCES) encountered while executing jQuery script with multiple ajax requests for 2 minutes

Upon initially loading the code below, everything seems to be functioning smoothly with the dayofweek and hourofday functions. However, shortly thereafter, the browser (Chrome) freezes up and displays the error message: net::ERR_INSUFFICIENT_RESOURCES. Thi ...

Guide to implementing 'active' state in Bootstrap 4 using JavaScript on a basic PHP website

A simple website consisting of three pages, designed using Bootstrap 4 framework. I have utilized includes to incorporate header.php and footer.php into the respective PHP pages below. My challenge lies in adding the 'active' class from Bootstrap ...

Modify the background color of paragraph using JavaScript based on the outcome

I am trying to update the background color of a search result in a paragraph tag based on a condition where the value of a variable is greater than 1. I believe this can be achieved using an if statement. Below is the code snippet I am currently working on ...

Having issues with Facebook's login API for JavaScript?

Apologies for the improper formatting. I am encountering errors in my JavaScript compiler while working with the Facebook Login API... Error: Invalid App Id - Must be a number or numeric string representing the application id." all.js:53 "FB.getL ...

Is there a way to determine the size of an array following the use of innerHTML.split?

There is a string "Testing - My - Example" I need to separate it at the " - " delimiter. This code will help me achieve that: array = innerHTML.split(" - "); What is the best way to determine the size of the resulting array? ...

What is the best way to utilize window.find for adjusting CSS styles?

Incorporating both AJAX and PHP technologies, I have placed specific text data within a span element located at the bottom of my webpage. Now, my objective is to search this text for a given string. The page consists of multiple checkboxes, with each check ...

The significance of the dollar sign in ReactJs

Why is the $ symbol placed after the 'add' and 'tab' in the activeKey and the tab in the given code snippet? addNum=0; onAdd=()=> { this.addNum++; let panes=Array.from(this.state.panes); let activeKey=`add$ { this.addNum ...

What is the best method to obtain the user id within a Redux action?

I am striving to display only user-related items, so I am attempting to retrieve items by sending a request for data to the user id /api/items/:userid. Utilizing Redux store in this process. Here is my server-side code snippet: router.get("/:userid", (req ...

AngularJS - Determine the correct condition or make a choice from the available options

I'm having trouble figuring out how to save the option I select to a viewmodel. The ng-model should save whatever option I choose, and if nothing is selected, the value should default to "Select One." The available options are YES (true) / NO (false). ...

Passing arguments to an external function in jQuery from a dynamically loaded Ajax page

Despite its confusing title, the issue at hand is actually quite simple. My homepage contains a script that loads an external PHP file for a specific section of my website. Within this PHP file, I need to call a function from the main JavaScript file (th ...