javascript - 在嵌套的 promise 链中重新抛出异常

标签 javascript angularjs promise angular-promise

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

注意:如果我删除内部 .catch() block ,我的 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用一个小演示来演示捕获异常并重新抛出它。

关于javascript - 在嵌套的 promise 链中重新抛出异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28290136/

相关文章:

javascript - 如何改变:visited to its parent color on refresh of the page的颜色

javascript - 尝试将标题标签添加到 mailto 链接,并在正文中添加 URL

angularjs - 使用angularjs,如何触发点击,或者有更好的方法?

javascript - 如何使用一系列异步请求的结果填充数组

javascript - NodeJS 的递归 Promise 不会终止

javascript - 从 UTC 字符串格式化日期

javascript - 在占位符 JSX 中渲染特殊字符

javascript - 类型错误 : Cannot read property '0' of undefined AngularJS

javascript - Angular $broadcast 仅在页面刷新时填充数据

javascript - 使用 promise 时的逻辑流程