AngularJS 组件模式在 Promise 后不更新

Posted

技术标签:

【中文标题】AngularJS 组件模式在 Promise 后不更新【英文标题】:AngularJS component modal not updating after a Promise 【发布时间】:2017-09-28 22:44:27 【问题描述】:

我创建了一个带有组件的示例 Angular js 应用程序,并尝试从 Promise 的 API 加载数据。

这里的问题是当 promise 被解决时,响应数据没有在 UI 中更新,如果我执行 $scope.$apply(),Modal 正在更新。我尝试了 $onChanges 但这也没有帮助!

这不是正确的实现,对吧?请提供有关我的代码结构和此问题的说明。

我在这里想念蚂蚁吗?

angular.module('detailapp', ['ui.router'])
    .component('app', 
        template: `
        <div class="container">
             <div ui-view></div>
        </div>
    `
    )
    .config(function ($stateProvider, $urlRouterProvider) 
        $urlRouterProvider.otherwise('/');
        //Home or Default page
        $stateProvider.state('home', 
            url: '/',
            template: '<div>Home</div>'
        );
        //details, with id
        $stateProvider.state('detail', 
            url: '/:id',
            template: '<detail-component></detail-component>'
        );

    )
    .service('endPointService', ['$q', '$http', function ($q, $http) 
        return 
            getDetailUrl: function (id) 
                return 'https://api.github.com/users/' + id;
            ,
            get: function (url, params) 
                return new Promise(function (resolve, reject) 
                    $http.get(
                        url, 
                            params: params
                        
                    ).then(function (res) 
                        resolve(res);
                    ).catch(function (err) 
                        reject(err);
                    );
                );
            
        
    ])
    .factory('listService', ['endPointService', function listService(endPointService) 
        let serviceInstance = ;
        serviceInstance.getDetail = function (Id) 
            return endPointService.get(
                endPointService.getDetailUrl(Id)
            ).then((res) => 
                return res.data;
            );
        ;
        return serviceInstance;
    ])
    .component('detailComponent', 
        template: `
    <div class="panel panel-default ">
      <div class="panel-heading">Detail Component: ID - vm.id</div>
        <div class="row">
                <div class="col-md-3 col-xs-3"><strong>Name</strong></div>
                <div class="col-md-9 col-xs-9"><span class="text-info pull-left">vm.obj.name</span>	       	       </div>
      </div>
      <div class="row">
                <div class="col-md-3 col-xs-3"><strong>Follow</strong></div>
                <div class="col-md-9 col-xs-9"><span class="text-info pull-left">vm.obj.followers_url</span>	       	       </div>
      </div>
    </div>`,
        controller: ['$scope', '$stateParams', 'listService', function detailController($scope, $stateParams, listService) 
            let vm = this;
            vm.id = $stateParams.id;
            vm.obj = ;
            vm.$onInit = function () 
                /*controller on init */
                vm.getDetails();
                console.log(`onInit $JSON.stringify(vm.obj)`);
            ;
            // vm.$onChanges = function (changes) 
            //     console.log(`onChanges $JSON.stringify(vm.obj) $JSON.stringify(vm.changes)`);
            //     // if (changes && angular.isUndefined(changes.obj.previousValue) && angular.isDefined(changes.obj.currentValue)) 
            //     //     console.log('Changing the modal' + changes);
            //     //     vm.obj = changes.obj.currentValue;
            //     // 
            // ;
            vm.getDetails = function () 
                listService.getDetail(vm.id).then(res => 
                    vm.obj = res;
                    $scope.$apply();
                    console.log(`api call $JSON.stringify(vm.obj)`);
                );

            ;
        ],
        controllerAs: 'vm'
    );
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.4/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.4.2/angular-ui-router.js"></script>

<body ng-app="detailapp">
    <div class="container-fluid">
        <app>app is loading here...!</app>
    </div>
</body>

【问题讨论】:

你的例子有用吗?请先修复它。你怎么去details 【参考方案1】:

在您的服务中,无需创建自定义承诺,因为 $http 返回的结果是承诺。只需返回请求

.service('endPointService', ['$q', '$http', function ($q, $http) 
        return 
            getDetailUrl: function (id) 
                return 'https://api.github.com/users/' + id;
            ,
            get: function (url, params) 
                return $http.get(url)
            
        
    ])

再次在工厂中返回服务方法,而不是在其中解开承诺

.factory('listService', ['endPointService', function listService(endPointService) 
        let serviceInstance = ;
        serviceInstance.getDetail = function (Id) 
            return endPointService.get(endPointService.getDetailUrl(Id))
        ;
        return serviceInstance;
    ])

【讨论】:

我不确定在 $http 上放置 Promise 有什么问题,现在问题已经解决。你能

以上是关于AngularJS 组件模式在 Promise 后不更新的主要内容,如果未能解决你的问题,请参考以下文章

使用 angularJS 和 Typescript 的 Promise

给你一个承诺 - 玩转 AngularJS 的 Promise

如何在 AngularJS 中实现组件组合(类似于 React 渲染道具模式)?

AngularJS2 学习笔记5 Async Data Binding

[AngularJS] AngularJS系列 进阶篇之promise

如何在angularjs中链接promise错误函数