The commitment remained unfulfilled following a validation error

I have a login form that uses the promise object for authentication. Everything works smoothly except when the form validation is triggered. Below is my HTML code:

   <form id="signin" class="signinform" autocomplete="off"> 
   <span ng-show="errorName" class="error_block">{{ errorName }}</span>
   <input placeholder="User Name" ng-model="user.name" type="text" name="user_name" required>
   <input placeholder="Password" ng-model="user.password" type="password" name="password" required>
  <input type="submit" ng-click="submit(user)" value="Log IN" id="submit">
</form>

The controller with the ng-click function is shown below:

  $scope.submit =  function(user){
   LoginService.login(user)
    .then(function(response) {           
         var userInfo = response.userName
         $rootScope.$emit('myEvent',userInfo);
         $location.path("/details/1");
    },
    function(error) {
      $scope.errorName = "Invalid Username or Password";
    });
 }

This is the factory service:

app.factory("LoginService", function($http, $q, $window) {
var userInfo;
var deferred = $q.defer();
 function login(user) {
  $http({
   method: 'POST',
   url: "login.php",
   data: { "userName": user.name, "password": user.password },
   headers: {'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'}
   }).then(function(result) { 
   userInfo = {
    accessToken: result.data.login.token,
    userName: result.data.login.name
   };
   $window.sessionStorage["userInfo"] = JSON.stringify(userInfo);  
    deferred.resolve(userInfo);
    }, function(error) {
    deferred.reject(error);
   });      
   return deferred.promise;
   }

   return {
    login: login
   };
 });

If the login fails due to incorrect credentials, an error message will be displayed. However, even after entering correct credentials, you may not be redirected to the details page and still see the same error message. But upon refreshing the page, you are already logged in. This issue seems to be related to the execution of the `then` function in the `$scope.submit`. I have tried various methods like `scope.apply` but haven't found a solution yet. Any help would be appreciated.

Answer №1

In agreement with @Akis, it is important to note that a deferred can only be created once and once it is fulfilled or rejected, that action stands permanently for that promise. This is because a promise can only be "resolved" once, whether it is fulfilled or rejected.

On a side note, there seems to be confusion in the terminology used with promises - a resolved promise actually means either fulfilled or rejected, yet many examples use the term resolve to indicate fulfillment!!

This response is provided to highlight that using deferred may not be necessary at all, especially considering that $http already returns a promise. In this scenario, utilizing deferred (or the new Promise constructor) could be deemed as an anti-pattern.

Additionally, I included

$window.sessionStorage.removeItem("userInfo");
just before the execution of $http - clearing sessionInfo at that point appears to be a logical step.

app.factory("LoginService", function($http, $q, $window) {
    function login(user) {
        // Added this step as it seemed appropriate!
        $window.sessionStorage.removeItem("userInfo");
        return $http({
            method: 'POST',
            url: "login.php",
            data: {
                "userName": user.name,
                "password": user.password
            },
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
            }
        }).then(function(result) {
            var userInfo = {
                accessToken: result.data.login.token,
                userName: result.data.login.name
            };
            $window.sessionStorage["userInfo"] = JSON.stringify(userInfo);
            return userInfo;
        });
    }
    return {
        login: login
    };
});

Answer №2

The reason for this behavior is that the promise has already been fulfilled.

Consider moving your $q.defer() initialization inside the login function instead of outside it.

function login(user) {
  var deferred = $q.defer();

  $http({
   method: 'POST',
   url: "login.php",
   data: { "userName": user.name, "password": user.password },
   headers: {'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'}
   }).then(function(result) { 
   userInfo = {
    accessToken: result.data.login.token,
    userName: result.data.login.name
   };
   $window.sessionStorage["userInfo"] = JSON.stringify(userInfo);  
    deferred.resolve(userInfo);
    }, function(error) {
    deferred.reject(error);
   });      
   return deferred.promise;
   }

   return {
    login: login
   };

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

When refreshing, the useEffect async function will not execute

Upon page load, the getImages function is intended to run only once. After refreshing the page, both tempQuestionImages and questionImages are empty. However, everything works perfectly after a hot reload. I am utilizing nextJs along with Firebase Cloud ...

Struggling to populate dropdown with values from array of objects

My issue is related to displaying mock data in a dropdown using the SUIR dropdown component. mock.onGet("/slotIds").reply(200, { data: { slotIds: [{ id: 1 }, { id: 2 }, { id: 3 }] } }); I'm fetching and updating state with the data: const ...

Selecting options from a pop-up menu

I've created a dropdown menu with what seems to be correct code. However, there are no errors showing up, but the selected item from the menu is not alerting as expected. Here is the jsfiddle link $(document).ready(function () { // This function ...

JavaScript Class Emit Signal for establishing a sequence of interconnected events

My Vue project includes a JavaScript class specifically for mobile devices. I'm looking to have this class emit a signal once the property 'hasEnded' is set to True for my object. How can I achieve this and chain together other events based ...

Clicking on the search box will remove the item that is currently displayed

Currently, I am working on creating a dropdown menu that includes a text box. The goal is for the items to appear when the text box is clicked, and for the selected item to turn green once clicked and then display in the text box. I'm interested in fi ...

Obtain the indices of a 2D array jQuery element within a callback function

I am working with a 2D array of JQuery elements, also known as a Grid. My goal is to access the specific index i and j of the element Grid[i][j] from within the callback function of an addEventListener(). Does anyone know how I can achieve this? grid[i][ ...

Using v-for to pass two properties to a single component in VueJS

Hey there! I'm trying to create a v-for loop with a component that has two different props COMPONENT <template> <div class="bg-light rounded p-2 px-5"> <h5> {{ number }}</h5> <h3>{{ item }} ...

Experiment with using webdriverio and javascript to select checkboxes

Currently, I am experimenting with testing the selection of checkboxes using webdriverio in combination with mocha and chai. Below is an example of what I attempted utilizing a javascript module pattern select_checkbox: function(browser, key, value){ r ...

Is there a way to continue a failed fetch request?

I am curious about the possibility of resuming an incomplete fetch request if it fails due to a non-code-related issue, like a lost network connection. In one of my current projects, we send a large download via AJAX to the client after they log in. This ...

Organize arrays within arrays in Javascript

My array of data is structured for visualization as shown below: var Dataset1 = [ { "commentBy": "saurabh", "comment": "Testing", "datestamp": "07/07/2017", "weekcount": 1 }, { "commentBy": "raman", "comment": "Planning", ...

Is there a way to retrieve the request URL within the validate function of the http strategy?

Is it possible to access the context object present in guards within the validate method of my bearer strategy, by passing it as an argument along with the token? bearer-auth.guard.ts: @Injectable() export class BearerAuthGuard extends AuthGuard('be ...

The command 'create-react-app' is not valid and cannot be recognized as an internal or external command, operable program, or batch file

I've been struggling to set up a React project, as the create-react-app my-app command doesn't seem to be working. Can anyone offer some assistance? Here are the commands I'm using: npm install -g create-react-app create-react-app my-app ...

Guidelines for adjusting the next/image component to a full 100% height

In my Next.js application, I am trying to display an image that fills the full height of its container while automatically adjusting its width based on its aspect ratio. I attempted the following method: <Image src="/deco.svg" alt=&qu ...

Guide on Generating Dynamic JSON to Set and Retrieve Values for Forms and Displaying the Bound Values

I'm a beginner in Ionic 3 and I'm having trouble creating a page that redirects to another page without validation. I want to display the data on the new page, but it's not working. Please help! I also want to create a dynamic JSON object a ...

What is the best way to send the input text to the filter component in my React application?

I am currently working on developing an application utilizing the "Rick and Morty API" to display a list of characters with various attributes such as gender, alive status, images, etc. My main goal is to implement a search bar that allows users to search ...

Obtain the title of the text generated by clicking the button using a script function

I am working on a piece of code that generates a text box within a button's onclick function. My goal is to retrieve the name value of each text box using PHP. <script language="javascript"> var i = 1; function changeIt() ...

Chart of commitments and potential outcomes

I am in the early stages of learning about promises and I am struggling to understand how to write code correctly. Here is an overview of what the program should do: Retrieve a list of item types (obtained through a promise) Loop through each item type to ...

various locations within a hexagonal zone or figure

In my project, I am working with a simple hexagonal grid. My goal is to select a group of hexagons and fill them with random points. Here is the step-by-step process of generating these points: I start by selecting hexagons using a list of hex coordinat ...

Leveraging Iframes for efficient user authentication within an Angular application

Incorporating an Iframe into one of my templates for authentication has presented certain challenges. Case in point: When a user finishes a training session, they must verify their identity by authenticating with a ping identity server that will redirect ...

The customization of a class within an array loop is not functioning properly

I'm facing an issue where I've added a class (question) to each element in an array, and the loop is running smoothly. However, I'm having trouble getting jQuery to recognize the class - it's almost as if it doesn't exist... I sus ...