Chris Jeong
Chris Jeong

Reputation: 185

Angularjs ui-router resolve does not wait for all promises

Currently, I'm having trouble with waiting for my promises to pass to resolve. I understand that it's because it is an async call so the resolve doesn't wait for all of the promises, and just passes in part of my data to resolve.

I've tried searching lot of forums but i can't seem to get it to work.

so here is my home page.

angular.module('app')
    .component('home', {
        templateUrl: 'Content/app/components/home.html',
        bindings: {},
        controller: ['$http', '$state', 'test',
            function ($http, $state, test) {
                var vm = this;
                vm.userName;

                vm.searchReddit = function () {
                    $http.get('https://www.reddit.com/user/' + vm.userName + '/about.json')
                        .then(function (response) {
                            vm.accountData = response.data.data;
                            vm.accountData.total_karma = vm.accountData.comment_karma + vm.accountData.link_karma;
                            $state.go('redditAnalyzer', { name: vm.userName });
                        });
                }
            }
        ]
    });

Once i type in my username, it changes state. and in my app.js i have

angular.module('app', ['ui.router', 'chart.js'])
    .config(['$stateProvider', '$urlRouterProvider', function ($stateProvider, $urlRouterProvider) {
        $urlRouterProvider.otherwise('/');
        $stateProvider
            .state('redditAnalyzer', {
                url: '/analyze/:name',
                component: 'redditAnalyzer',
                resolve: {
                    resolve:
                    ['test', '$stateParams', function (test, $stateParams) {
                        var data = test.getAnalysisData($stateParams.name);
                        return data;
                    }
                    ]
                }
            })
            .state('home', {
                url: '/',
                component: 'home'
            });
    }]);

I'm calling the function test.getAnalysisData to get the data.

and in my test.js I have

angular.module('app')
    .factory('test', ['$http', '$state', '$q', function ($http, $state, $q) {
        var vm = this;

        vm.accountData = {};
        vm.after = '';
        vm.bestComment = {};
        vm.bestComment.karma = 0;
        vm.userName;
        vm.bestComment.date = '';
        vm.subreddit = {};
        vm.myChart;

        vm.getAnalysisData = function (redditUser) {
            vm.userName = redditUser;
            vm.resetData(redditUser);
            vm.getAccountInfo(redditUser);
            vm.getAllComments(redditUser);
            return {
                accountData: vm.accountData,
                bestComment: vm.bestComment,
                userName: vm.userName,
                subreddit: vm.subreddit,
                myChart: vm.myChart
            };
        }

        vm.resetData = function (user) {
            vm.accountData = {};
            vm.after = '';
            vm.bestComment = {};
            vm.bestComment.karma = -(Math.pow(2, 53) - 1);
            vm.userName = user;
            vm.date = '';
            vm.subreddit = [];
            vm.topThreeSub = [];
        }

        vm.getAccountInfo = function (user) {
            $http.get('https://www.reddit.com/user/' + user + '/about.json')
                .then(function (response) {
                    vm.accountData = response.data.data;
                    vm.accountData.total_karma = vm.accountData.comment_karma + vm.accountData.link_karma;
                    console.log("I got the account info!");
                });
        }
        vm.getAllComments = function (user) {
            $http.get('https://www.reddit.com/user/' + user + '/comments.json' + vm.after)
                .then(
                function (response) {
                    console.log("I got the comment info!");
                    tempResponse = response;
                    var data = response.data.data
                    vm.after = '?after=' + data.after;
                    for (i = 0; i < data.children.length; i++) {
                        if (vm.bestComment.karma < parseInt(data.children[i].data.score)) {
                            vm.bestComment.karma = parseInt(data.children[i].data.score);
                            vm.bestComment.comment = data.children[i].data.body;
                            vm.bestComment.date = (new Date(data.children[i].data.created * 1000)).toString();
                        }
                        var tempSub = data.children[i].data.subreddit;
                        if (vm.subreddit[tempSub] === undefined) {
                            vm.subreddit[tempSub] = 1;
                        }
                        else {
                            vm.subreddit[tempSub]++;
                        }
                    }
                    if (response.data.data.after != null) {
                        vm.getAllComments(user);
                    }
                }, function (error) {
                    console.log(error);
                    throw error;
                })
                .catch(function (error) { });
        }
        return {
            resolve: vm.resolve,
            hello: vm.hello,
            getAnalysisData: vm.getAnalysisData
        }
    }]);

I'm recursively calling the function vm.getAllComments because how it works is vm.getAllComments will get first 25 comments of the account, and then from part of the info from response, I can get the next 25 comments in the account.

and finally, in my redditanalyzer file, I have

angular.module('app')
    .component('redditAnalyzer', {
        templateUrl: 'Content/app/components/redditAnalyzer.html',
        bindings: {
            resolve: '<'
        },
        controller: ['$http', 'test',
            function ($http, test) {
                var vm = this;
                vm.accountData = {};
                vm.bestComment = {};
                vm.bestComment.karma = 0;
                vm.userName;
                vm.bestComment.date = '';
                vm.subreddit = {};
                vm.myChart;

                vm.$onInit = function () {
                    console.log("this is the resolve", vm.resolve);
                    //vm.accountData = resolve.accountData;
                    //vm.bestComment = resolve.bestComment;
                    //vm.myChart = resolve.myChart;
                    //vm.subreddit = resolve.subreddit;
                    //vm.userName = resolve.userName;
                }

            }]
    });

And you can see the problem in my console.

this is the resolve {accountData: {…}, bestComment: {…}, userName: "spez", subreddit: Array(0), myChart: undefined}accountData: {}bestComment: {karma: 22200, comment: "Reddit search might work by then.", date: "Thu Oct 27 2016 01:07:22 GMT-0400 (Eastern Daylight Time)"}myChart: undefinedsubreddit: [blog: 10, announcements: 475, modnews: 34, programming: 32, ModSupport: 20, …]userName: "spez"__proto__: Object
test.js:44 I got the account info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
test.js:51 I got the comment info!
7test.js:51 I got the comment info!

It changes the route even before doing the promises. What should i do to wait for all of my promises?

Upvotes: 0

Views: 530

Answers (2)

user9050642
user9050642

Reputation:

I additional, what version of ui-router you are using? on the latest '$stateParams' is deprecated and relapsed with $transition$.

Also you don`t need to use this

url: '/analyze/:name',

In UI-Router legacy, a parameter found in the URL path was optional. If the parameter was not found in the URL, it would match the empty string.

You can replace with:

url: '/analyze/', 

and

params: {
    name: ""
  }

You can read migration guid

Upvotes: 0

georgeawg
georgeawg

Reputation: 48968

The resolver doesn't wait for the promise because the code doesn't return a promise to the resolver.

The getAllComments function needs to return a promise:

    vm.getAllComments = function (user) {
         ̲r̲e̲t̲u̲r̲n̲ $http.get('https://www.reddit.com/user/' + user + '/comments.json' + vm.after)
            .then(
            function (response) {
                console.log("I got the comment info!");
                tempResponse = response;
                var data = response.data.data
                vm.after = '?after=' + data.after;
                for (i = 0; i < data.children.length; i++) {
                    if (vm.bestComment.karma < parseInt(data.children[i].data.score)) {
                        vm.bestComment.karma = parseInt(data.children[i].data.score);
                        vm.bestComment.comment = data.children[i].data.body;
                        vm.bestComment.date = (new Date(data.children[i].data.created * 1000)).toString();
                    }
                    var tempSub = data.children[i].data.subreddit;
                    if (vm.subreddit[tempSub] === undefined) {
                        vm.subreddit[tempSub] = 1;
                    }
                    else {
                        vm.subreddit[tempSub]++;
                    }
                }
                if (response.data.data.after != null) {
                     ̲r̲e̲t̲u̲r̲n̲ vm.getAllComments(user);
                } else {
                     ̲r̲e̲t̲u̲r̲n̲ ̲v̲m̲.̲b̲e̲s̲t̲C̲o̲m̲m̲e̲n̲t̲;̲
                }
            }, function (error) {
                console.log(error);
                throw error;
            })
            ̶.̶c̶a̶t̶c̶h̶(̶f̶u̶n̶c̶t̶i̶o̶n̶ ̶(̶e̶r̶r̶o̶r̶)̶ ̶{̶ ̶}̶)̶;̶
    }

Use $q.all to create a promise that waits for multiple promises:

    vm.getAnalysisData = function (redditUser) {
        vm.userName = redditUser;
        vm.resetData(redditUser);
        vm.getAccountInfo(redditUser);
        ̲v̲a̲r̲ ̲a̲l̲l̲C̲o̲m̲m̲e̲n̲t̲s̲P̲r̲o̲m̲i̲s̲e̲ ̲=̲ vm.getAllComments(redditUser);
        return $q.all({
            accountData: vm.accountData,
            bestComment: vm.bestComment,
            userName: vm.userName,
            subreddit: vm.subreddit,
            myChart: vm.myChart,
            ̲a̲l̲l̲C̲o̲m̲m̲e̲n̲t̲s̲:̲ ̲a̲l̲l̲C̲o̲m̲m̲e̲n̲t̲s̲P̲r̲o̲m̲i̲s̲e̲
        });
    }

For more information, see

Upvotes: 1

Related Questions