【问题标题】:TypeError: Cannot read property '$promise' of undefined with using ngResource in angularJSTypeError:无法在angularJS中使用ngResource读取未定义的属性'$promise'
【发布时间】:2017-06-22 04:44:08
【问题描述】:

我在我的 angularJS 应用程序中使用 ngResource 创建了一个服务,以将一些数据发送到我的 rest api。

在我发送请求后,我想使用一个 Promise 在我的控制器中执行一些任务。

这是我的服务:

angular.module("MyService", ['ngResource'])

.factory("myService",  function ($rootScope, $http, $resource) {

    var apiData = $resource(
        "/api", {},
        {

                  "postQuestion": { method: "POST", url: "/api/:userid"}

        });

        return {

            postQuestion: function(question,  user_id) {
                apiData.postQuestion({ userid: user_id}, question, function(data) {
                    console.log("Sucsess !");
                }, function(error) {
                    console.log("Error " + error.status + " when sending request : " + error.data);
                });

            }
    }
});

这是我在控制器中使用它的方式:

app.controller("MyCtrl", function ($scope, $filter,  $http, $sce, myService, ngDialog, $rootScope, $location) {


$scope.postQuestion = function(newQuestion)
{

    myService.postQuestion(newQuestion, 1).$promise.then(function(){
        $scope.showNewQuestion = false;
        $location.path("/");
    });
}


})

但是在运行我的应用程序时,我的控制台中出现了这个错误:

TypeError:无法读取未定义的属性“$promise” 在 Scope.$scope.postQuestion ...

不知道为什么,请帮忙

【问题讨论】:

  • 您是否尝试过从服务方法实际返回 apiData.postQuestion 的结果?

标签: angularjs rest promise factory ngresource


【解决方案1】:

postQuestion 函数缺少 return 语句:

    postQuestion: function(question,  user_id) {
        //vvvv RETURN the resource object
        return apiData.postQuestion({ userid: user_id}, question, function(data) {
            console.log("Sucsess !");
        }, function(error) {
            console.log("Error " + error.status + " when sending request : " + error.data);
        });

    }

当函数省略return 语句时,它返回值undefined。因此错误消息:

TypeError: Cannot read property '$promise' of undefined at ...

没有必要使用$q.defer() 制造承诺,因为$resource 服务已经返回附加到资源对象的承诺作为$promise 属性。

Resource 实例和集合具有以下附加属性:

  • $promise:创建此实例或集合的原始服务器交互的承诺。

成功后,promise 将使用相同的资源实例或集合对象进行解析,并使用来自服务器的数据进行更新。这使得在$routeProvider.when() 的解析部分中使用它可以很容易地推迟视图渲染,直到资源加载。

如果失败,则使用 http response 对象拒绝承诺,没有资源属性。

如果提供了拦截器对象,promise 将改为使用拦截器返回的值来解析。

-- AngularJS $resource API Reference

【讨论】:

  • 是的,非常正确?!非常感谢,这样更简单???
  • 我认为可能有更好的方法,我没有处理太多$resource,是的更好的方法。只是因为我没有建议而生气,该死!
【解决方案2】:

myService 中的这个函数没有返回一个承诺:

postQuestion: function(question,  user_id) {
    apiData.postQuestion({ userid: user_id}, question, function(data) {
        console.log("Sucsess !");
    }, function(error) {
        console.log("Error " + error.status + " when sending request : " + error.data);
    });
}

但控制器中的调用代码需要一个:

myService.postQuestion(newQuestion, 1).$promise.then(function(){
    $scope.showNewQuestion = false;
    $location.path("/");
});

要解决此问题,您可以使用 $q 库创建自己的承诺,然后根据需要解决或拒绝它,然后将该承诺返回给控制器:

postQuestion: function(question,  user_id) {
    var deferred = $q.defer();
    apiData.postQuestion({ userid: user_id}, question, function(data) {
        console.log("Sucsess !");
        deferred.resolve(data);
    }, function(error) {
        console.log("Error " + error.status + " when sending request : " + error.data);
        deferred.reject(error);
    });
    return defered.promise;
}

然后你可以从调用代码中删除$promise,并在myService.postQuestion的返回值上调用then函数(现在是一个promise):

myService.postQuestion(newQuestion, 1).then(function(){
    $scope.showNewQuestion = false;
    $location.path("/");
});

【讨论】:

  • 我收到了这个新错误:TypeError: Cannot read property 'then' of undefined
  • 啊,是的,从控制器的调用代码中删除 $promise 部分。我也会更新我的帖子。
猜你喜欢
  • 2016-07-28
  • 2014-11-26
  • 2018-01-15
  • 2018-06-02
  • 2015-08-26
  • 2016-09-12
  • 2016-11-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多