在嵌套承诺链中重新引发异常

Rethrowing exceptions in nested promise chains

本文关键字:新引发 异常 嵌套 承诺      更新时间:2023-09-26

我试图找出一种在 AngularJs 中链接承诺的干净方法。我的目标是不使用 $q 重新包装 $http 承诺,而是利用 $http.xxx() 方法返回承诺并使用链接的事实。在下面的代码中,我试图满足以下用例。

注意:如果我删除 innner .catch() 块,我的 404 将被外部 catch() 捕获。我尝试使用then(actionHandler,errorHandler)方法,并尝试从.catch()返回字符串,并尝试在.catch()中使用this.reject()。

Give $scope.username is Bret 
When calling getPosts() and getting a 404 from /users 
Then scope.error has a message indicating that the user wasn't found

//法典

angular.module('app', [])
    .controller('MainController', function ($scope, $log, $q, $http) {
        $scope.posts = [];
        $scope.message = "";
        function getUserByUserName(userName) {
            return getUsers()
                .then(function (response) {
                    var user;
                    for (var i = 0; i < response.data.length; i++) {
                        if (response.data[i].username === userName) {
                            user = response.data[i];
                            break;
                        }
                    }
                    return user;
                }).catch(function (error) {
                    throw "User could not be found.";
                });
        };
        function getUsers() {
            return $http.get('http://jsonplaceholder.typicode.com/users');
        }
        function getPostByUser(user){
            return getPosts()
                .then(function (posts) {
                    var postsByUser = [];
                    for (var i = 0; i < posts.length; i++) {
                        if (posts[i].userId === user.id) {
                            postsByUser.push(posts[i]);
                        }
                    }
                    return postsByUser;
                });
        }
        function getPosts() {
            return $http.get('http://jsonplaceholder.typicode.com/posts')
                .then(function (response) {
                    return response.data;
                });
        };
        function addPostsToScope(posts) {
            $log.debug('MainController.getPostByUserName reponse.length: ' + posts.length);
            $scope.posts.length = 0;
            $scope.posts.username = $scope.username;
            for (var i = 0; i < posts.length; i++) {
                $scope.posts.push(posts[i]);
            }
        };
        $scope.getPosts = function () {
            getUserByUserName($scope.username)
                .then(getPostByUser)
                .then(addPostsToScope)
                .catch(function (error) {
                        $scope.error = error;
                });
        };
    });

//测试

describe('MainController', function () {
var endpointController;
var dummyPosts = [
    {
        "userId": 1,
        "id": 1,
        "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
        "body": "quia et suscipit'nsuscipit recusandae consequuntur expedita et cum'nreprehenderit molestiae ut ut quas totam'nnostrum rerum est autem sunt rem eveniet architecto"
    },
    {
        "userId": 1,
        "id": 2,
        "title": "qui est esse",
        "body": "est rerum tempore vitae'nsequi sint nihil reprehenderit dolor beatae ea dolores neque'nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis'nqui aperiam non debitis possimus qui neque nisi nulla"
    },
    {
        "userId": 2,
        "id": 11,
        "title": "et ea vero quia laudantium autem",
        "body": "delectus reiciendis molestiae occaecati non minima eveniet qui voluptatibus'naccusamus in eum beatae sit'nvel qui neque voluptates ut commodi qui incidunt'nut animi commodi"
    }];
var dummyUsers = [
    {
        "id": 1,
        "name": "Leanne Graham",
        "username": "Bret",
        "email": "Sincere@april.biz",
        "address": {
            "street": "Kulas Light",
            "suite": "Apt. 556",
            "city": "Gwenborough",
            "zipcode": "92998-3874",
            "geo": {
                "lat": "-37.3159",
                "lng": "81.1496"
            }
        },
        "phone": "1-770-736-8031 x56442",
        "website": "hildegard.org",
        "company": {
            "name": "Romaguera-Crona",
            "catchPhrase": "Multi-layered client-server neural-net",
            "bs": "harness real-time e-markets"
        }
    },
    {
        "id": 2,
        "name": "Ervin Howell",
        "username": "Antonette",
        "email": "Shanna@melissa.tv",
        "address": {
            "street": "Victor Plains",
            "suite": "Suite 879",
            "city": "Wisokyburgh",
            "zipcode": "90566-7771",
            "geo": {
                "lat": "-43.9509",
                "lng": "-34.4618"
            }
        },
        "phone": "010-692-6593 x09125",
        "website": "anastasia.net",
        "company": {
            "name": "Deckow-Crist",
            "catchPhrase": "Proactive didactic contingency",
            "bs": "synergize scalable supply-chains"
        }
    }];
beforeEach(module('app'));
it('Give $scope.username is Bret When calling getPosts() and getting a 404 from /users Then scope.error has a message indicating that the user wasnt found',
    inject(function ($rootScope, $controller, $httpBackend) {
        $httpBackend.whenGET('http://jsonplaceholder.typicode.com/users')
            .respond(404, null, null, "Not Found");
        $httpBackend.whenGET('http://jsonplaceholder.typicode.com/posts')
            .respond(dummyPosts);
        var scope = $rootScope.$new();
        scope.username = 'Bret';
        endpointController = $controller("MainController", { $scope: scope });
        scope.getPosts();
        $httpBackend.flush();
        expect(endpointController).toBeTruthy();
        expect(scope.error).toBeTruthy();
        expect(scope.error).toBe("User could not be found.");
    }));

});

编辑我在这里添加了一个显示问题的 plunker:http://plnkr.co/edit/URMFfeM9IHPUGDbydZfa?p=preview

预期的控制台输出为

That user could not be found.
outer catch block reached!

但它正在写出来

That user could not be found.
getPosts
getPosts.Then()
getPostsByUser()

在捕获中使用return $q.reject(error)

return getUsers()
    .then(function (response) {
        var user;
        for (var i = 0; i < response.data.length; i++) {
            if (response.data[i].username === userName) {
                user = response.data[i];
                break;
            }
        }
        return user;
    }).catch(function (error) {
        return $q.reject(error);
    });

Plunkr 有一个小型演示,演示如何捕获异常并重新抛出它。