【问题标题】:AngularJS service function not returning full promise after while loop has completedAngularJS服务功能在while循环完成后没有返回完整的承诺
【发布时间】:2019-09-20 09:17:23
【问题描述】:

我正在尝试对地图进行分页。我想强制控制器等待执行分页的服务返回所有可用产品,然后再尝试执行任何操作。

我在我的路由器中实现了一个解析函数,它将调用执行分页的服务(使用 while 循环)并获取结果。

在运行代码时,控制器内部的“产品”数量始终为全部数量的 1/2 或 2/3,具体取决于所使用的浏览器。控制器在 while 循环完成运行/返回所有承诺之前进行初始化。对于如何强制控制器等待获取 while 循环的所有结果,我有点困惑。我是否需要更改我的服务功能、我的控制器或路由器(或全部三个?)。还是说我对$q库的使用不正确?

在我的路由器内部:

    .state('products-map', {
        url: "/products-map",
        parent: 'base',
        templateUrl: "../components/products/products.map.html",
        data: { pageTitle: 'Products Map', pageSubTitle: 'map of all the products'},
        controller: "ProductsMapController",
        resolve: {
            deps: ['$ocLazyLoad', function($ocLazyLoad) {
                return $ocLazyLoad.load({
                    name: 'myApp',
                    insertBefore: '#ng_load_plugins_before',
                    files: [
                        { type: 'js', path: '//maps.google.com/maps/api/js?v=3&key=<my_api_key>&libraries=visualization,geometry'},
                        '../js/markerclusterer_packed.js',
                    ]
                });
            }],

            total_products: function(DashboardService) {
                return DashboardService.getTotalProducts();
            },

            products: function(DashboardService, total_products){
                return DashboardService.getPaginatedProducts(total_products);
            },

        }
    })

在我处理分页的服务函数内部:

this.getPaginatedProducts = function(total_product_count) {

    var total_fetched_results = 0;
    var total_number_of_products = total_product_count;
    console.log("total number of products in paginated products: ", total_number_of_products);
    var results_per_page = 20000;
    var page = 1;
    var products = [];

    var deferred = $q.defer();

    while (total_number_of_products > total_fetched_results) {

        $http({
            url: $rootScope.apiUrl + 'products/location',
            method: "GET",
            params: { 'results_per_page': results_per_page, 'page': page}
        }).then(function(response) {
            console.log("response from service", response);
            var response_data = response.data.data;
            for (var i = 0; i < response_data.length; i++) {
                products.push(response_data[i]);
            }
        });

        page++;
        total_fetched_results += results_per_page;
    }

    deferred.resolve(products);
    return deferred.promise;
};

在我的控制器内部:

angular.module('SS2').controller('ProductsMapController', ['$rootScope', 'products', '$scope', '$http', 'NgMap', 'total_products',
    function ($rootScope, products, $scope, $http, NgMap, total_products) {

        $scope.$on('mapInitialized', function (event, map) {

            console.log("ProductsMapController Initialised")
            console.log("total_products inside ProductsMapController is: ", total_products);
            $scope.map_products = products;
            console.log("inside controller number of products is: ", products);

【问题讨论】:

  • 您对 $q 库的使用不正确。避免使用deferred anti-pattern。使用 $q.all 将多个 Promise 组合成一个 Promise,当所有输入 Promise 都被解析时,该 Promise 被解析。

标签: angularjs angular-ui-router angular-promise


【解决方案1】:

您可以在这里采取一些方法,使用 Promise 肯定是有意义的。我所看到的 while 循环是一个逻辑缺陷,在您的函数达到退出条件之前,您的 $http 请求并未全部解决。

您可能需要考虑使用 $q.all() 并构建一个 $http 调用数组,以确保在返回结果之前解决所有问题,正如我怀疑的那样,当您查看网络监视器时,您会看到在呈现结果之前未解决调用。

https://docs.angularjs.org/api/ng/service/$q#all

一个很好的例子是https://chariotsolutions.com/blog/post/angularjs-corner-using-promises-q-handle-asynchronous-calls/

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-25
相关资源
最近更新 更多