【问题标题】:Angularjs/Ionic TypeError: Cannot read property 'then' of undefinedAngularjs/Ionic TypeError:无法读取未定义的属性“then”
【发布时间】:2015-03-28 09:15:02
【问题描述】:

代码: js:

angular.module('starter.services', ['ngResource'])
.factory('GetMainMenu',['$http','$q','$cacheFactory',function($http,$q,$cacheFactory) {
            var methodStr = 'JSONP';
            var urlStr = 'http://localhost/bd/wp-admin/admin-ajax.php';
            var ptStr = {action:'bd_get_main_menus',callback:'JSON_CALLBACK'};

            return {
                getMainMenuItems: function(){
                    var deferred = $q.defer();

                  $http.jsonp(urlStr,{params: ptStr})
                        .success(function (data, status) {

                            deferred.resolve(data);

                            return deferred.promise;
                        })
                        .error(function (data, status) {

                            deferred.reject(data);

                            return deferred.promise;

                        });
                }
            }

        }])

angular.module('starter.controllers', [])
.controller('AppCtrl', function($scope, $ionicModal, $timeout, $http,GetMainMenu) {
    GetMainMenu.getMainMenuItems().then(
      function(data){
        $scope.mainMenus = data;
      });
});

运行结果:

TypeError:无法读取未定义的属性“then” 在新的 (ht.../www/js/controllers.js:42:33) 在调用 (ht.../www/lib/ionic/js/ionic.bundle.js:11994:17)...

这些代码哪里出错了?

【问题讨论】:

  • "Cannot read property 'then' of undefined" 你的 GetMainMenu.getMainMenuItems() 是未定义的,它应该是调用 then() 方法的 promise 对象。格式化您的代码。
  • 不要使用deferred antipattern

标签: javascript angularjs ionic


【解决方案1】:

您需要从 getMainMenuItems 函数返回 deferred.promise,而不是在用于 $http.jsonp 的回调函数中返回。这是因为getMainMenuItems 需要返回一个承诺。

angular.module('starter.services', ['ngResource'])
.factory('GetMainMenu',['$http','$q','$cacheFactory',function($http,$q,$cacheFactory) {
    var methodStr = 'JSONP';
    var urlStr = 'http://localhost/bd/wp-admin/admin-ajax.php';
    var ptStr = {action:'bd_get_main_menus',callback:'JSON_CALLBACK'};

    return {
        getMainMenuItems: function(){
            var deferred = $q.defer();

          $http.jsonp(urlStr,{params: ptStr})
                .success(function (data, status) {

                    deferred.resolve(data);
                })
                .error(function (data, status) {

                    deferred.reject(data);
                });

           return deferred.promise;
        }
    }
}])

另一种选择是只返回来自$http.jsonp 的承诺:

return {
        getMainMenuItems: function(){
           return $http.jsonp(urlStr,{params: ptStr});
        };

【讨论】:

  • @Bergi 可以通过使用上面建议的替代方案来避免延迟反模式。我同意最好避免延迟反模式。
【解决方案2】:

你应该在 $http 之外返回 promise 对象。 您也可以返回 $http,因为它是一个承诺,不需要有另一个承诺。

angular.module('starter.services', ['ngResource'])
  .factory('GetMainMenu', ['$http', '$q', '$cacheFactory', function ($http, $q, $cacheFactory) {
    var methodStr = 'JSONP';
    var urlStr = 'http://localhost/bd/wp-admin/admin-ajax.php';
    var ptStr = {action: 'bd_get_main_menus', callback: 'JSON_CALLBACK'};

    return {
      getMainMenuItems: function () {
        var deferred = $q.defer();

        $http.jsonp(urlStr, {params: ptStr})
          .success(function (data, status) {

            deferred.resolve(data);
          })
          .error(function (data, status) {

            deferred.reject(data);
          });
      return deferred.promise
      }
    }

  }])

angular.module('starter.controllers', [])
  .controller('AppCtrl', function ($scope, $ionicModal, $timeout, $http, GetMainMenu) {
    GetMainMenu.getMainMenuItems().then(
      function (data) {
        $scope.mainMenus = data;
      });
  });

【讨论】:

猜你喜欢
  • 2015-04-25
  • 2019-08-19
  • 2014-09-07
  • 1970-01-01
  • 1970-01-01
  • 2016-10-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多