Angular Promises - Going from the triumph to the disappointment callback?

It seems like I might be pushing the boundaries of what Promises were intended for, but nonetheless, here is what I am attempting to do:

$http.get('/api/endpoint/PlanA.json').then(
    function success( response ) {
        if ( response.data.isAllGood ) {
            $scope.myData = response.data;
        }
        else {
            // TODO HERE! Call the failure function!
        }
    },
    function failure() {
        $http.get('/api/endpoint/PlanB.json').then(
            function planBsuccess( response ) {
                $scope.myData = response.data;
            }
        );
    }
).then(function doOtherStuff() {});

This logic works fine when, for example, the PlanA endpoint returns a 404 or 500 error...but if it succeeds and the data is bad (e.g., isAllGood evaluates to false), I want it to trigger the failure callback. Is there a simple way to achieve this?

I have attempted to use $q.defer().reject and return that promise, but it only triggers the failure callback for doOtherStuff.

Answer №1

A convenient approach is available for accomplishing this task. To successfully execute it, ensure that the failure callback is chained after the success callback, rather than beside it. Refer to When is .then(success, fail) considered an antipattern for promises? for a more comprehensive explanation.

$http.get('/api/endpoint/PlanA.json').then(function success(response) {
    if (response.data.isAllGood) {
        $scope.myData = response.data;
    } else {
        return $q.reject(); // trigger promise failure
    }
}).catch(function failure() { // handling errors from $http as well
    return $http.get('/api/endpoint/PlanB.json').then(function planBsuccess(response) {
//  ^^^^^^ importantly, wait for plan B before proceeding with doOtherStuff
        $scope.myData = response.data;
    });
}).then(function doOtherStuff() {});

An alternative method could be utilized to minimize code duplication in the $scope assignment:

$http.get('/api/endpoint/PlanA.json').then(function validate(response) {
    if (response.data.isAllGood)
        return response;
    else
        throw new Error("noGoodData");
}).catch(function failure() {
    return $http.get('/api/endpoint/PlanB.json');
}).then(function success(response) {
    $scope.myData = response.data;
    return doOtherStuff();
});

Answer №2

Avoid it. It is not a good design choice. Here is a more straightforward alternative:

$http.get('/api/endpoint/PlanA.json').then(
    function success( response ) {
        if ( response.data.isAllGood ) {
            $scope.myData = response.data;
        }
        else {
             foo();
        }
    },
    function failure() {
        foo();
    }
).then(function doOtherStuff() {});

foo = function(){
  $http.get('/api/endpoint/PlanB.json').then(
        function planBsuccess( response ) {
            $scope.myData = response.data;
        }
   );
};

Having said that, I believe even this approach strays from the intended use of $http. A better practice would be something like

$http.get('/api/endpoint/PlanA.json').then(
    function success( response ) {
      $scope.myData = response.data;
    },
    function failure() {
        trueFailureFunc();
    }
).then(validateData());

validateData = function(){
    if ( response.data.isAllGood ) {
      $scope.myData = response.data;
    }
     else {
        getDataFromOtherSource();
    }
}

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

Swap out the image for a div element if the image is not found

Is there a way to accurately display an image if it's available, and use a div as a replacement if the image is not present? // How can I determine `imageExists` without encountering cross-origin issues? (imageExists) ? (<img class="avatar-img" sr ...

What is the best way to arrange the keys of a JavaScript object in a customized

I am struggling to find a way to custom sort a JavaScript object properly. For example, I have the following object: var test = { 'yellow': [], 'green': [], 'red': [], 'blue': [] } And an array with values ...

Explore three stylish ways to showcase dynamic JavaScript content using CSS

Objective: For Value 1, the CSS class should be badge-primary For Value 2, the CSS class should be badge-secondary For all other values, use the CSS class badge-danger This functionality is implemented in the handleChange function. Issue: Current ...

"Discover the step-by-step guide for incorporating password reset functionality in AngularJS using UI router

I am currently working on an AngularJS application that includes login, registration, and forgot password features implemented using JWT. Additionally, I am using UI Router for managing various states within the app. When a user clicks on the "forgot pass ...

Issue with preventDefault not functioning correctly within a Bootstrap popover when trying to submit a

I am facing an issue with a bootstrap popover element containing a form. Even though I use preventDefault() when the form is submitted, it does not actually prevent the submit action. Interestingly, when I replace the popover with a modal, the functional ...

Retrieving Ajax Data Using C#

I am struggling to send data through Ajax to a C# file. Whenever I check the received data, it always comes back as null. Could there be an issue in my code? Javascript file $(".save").click(function () { var ss = "Helloo!"; $.ajax({ typ ...

Choose a procedure to reset to the original setting

I'm attempting to achieve something that seems straightforward, but I'm having trouble finding a solution. I have a <select> tag with 5 <option> elements. All I want to do is, when I click a button (which has a function inside of it), ...

Retrieving information from PHP using AJAX

As a newcomer to the world of AJAX, I am faced with the task of retrieving data from a PHP file and storing it in a JavaScript variable. Despite exploring several examples, I have not been able to find a satisfactory solution. Here is a simplified HTML cod ...

Issues with Displaying Components Generated from an Array in JSX

I have a task variable which has the structure as follows: [ team_id_1: { task_id_1: { description: ... }, task_id_2: { description: ... } }, team_id_2: { ... } ] When trying ...

JavaScript problem indicating an error that is not a function

Recently, I've delved into the world of JavaScript and am currently exploring JavaScript patterns. I grasp the concepts well but struggle with calling functions that are already in an object. var productValues = 0; var cart = function(){ this. ...

The AngularJS $HTTP loop counter fails to update

When working with an HTTP service and binding JSON data to HTML, I implemented the following code: This function uses a 2-second timer to automatically fetch data whenever there is a change in the backend. function sampleDevices ...

Measuring data entries within JSON array utilizing JavaScript and Postman

A specific component is returning two records: { "value": [ { "ID": 5, "Pupil": 1900031265, "Offer": false, }, { "ID": 8, "Pupil": 1900035302, "Offer": false, "OfferDetail": "" } ] } My task i ...

Adaptive Container with Images that are not stretched to full width

Is there a way to achieve the same effect as seen in images 2 and 3 here: Although these images already have their own "padding," I'm curious if it can be replicated using just jQuery and CSS? I would appreciate any help or insights on this. Thank y ...

What is the reason behind the continual change in the background image on this website?

Can you explain the functionality of this background image? You can find the website here: ...

Next.js version 14 is having difficulties displaying the loading.tsx file

click here for image description Why is the loading not displaying when navigating to /profile? How can I fix this issue? export default function Loading() { // You can add any UI inside Loading, including a Skeleton. return ( <div> lo ...

ng-pattern for requiring whole numbers only with no decimal points

Looking for an ng-pattern to limit the entry of decimals in an input type number field. I attempted using ng-pattern="/^[0-9]$/" but it doesn't display an error when entering values like 1.0, 2.0, 3.0, etc. Example: 2.0 = fail 2 = pass 3.0=fail 3=p ...

Issue with AngularJS 1.2.0-rc3 compatibility causing Angular-ui-bootstrap typehead to malfunction

Take a look at this example showcasing the use of Angular-ui-bootstrap typeahead with AngularJS 1.0.5: http://plnkr.co/edit/me20JzvukYbK0WGy6fn4 The template includes ng-bind-html-unsafe, which is considered deprecated in AngularJS 1.2.0-rc3. Is there an ...

What is the best way to differentiate between a JSON object and a Waterline model instance?

Note: I have posted an issue regarding this on the Waterline repo, but unfortunately, I have not received a simpler solution than my current workaround. Within my User model, along with default attributes such as createdDate and modifiedDate, I also have ...

I'm currently attempting to establish a connection between my server.js express API and MongoDB, but I keep encountering an unfamiliar error message that I'm having trouble decipher

Here is the server.js code: import express from 'express'; import bodyParser from 'body-parser'; import userRoutes from './routes/users.js'; import mongoose from 'mongoose'; co ...

Encountered a "no login transports available" error while trying to use Firebase

Currently utilizing Firebase's AngularFire for Facebook logins and encountering an issue with the provided code. Below is my HTML code (including ng-click to initiate login): <a ng-click="loginWithFacebook()" class="btn btn-block btn-social btn- ...