我使用ngResource在angularJS应用中创建了一个服务,将一些数据发送到我的rest api。
我想在发送请求后立即使用承诺在我的控制器中执行某些任务。
这是我的服务:
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:无法读取undefined的属性'$ promise' 在Scope。$ scope.postQuestion ...
不知道为什么,请帮忙
答案 0 :(得分:2)
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:无法读取属性' $ promise'
undefined
的...... {/ p>
无需使用$q.defer()
生成承诺,因为$ resource服务已经将附加到资源对象的承诺作为$promise
属性返回。
资源实例和集合具有以下附加属性:
$promise
:创建此实例或集合的原始服务器交互的承诺。成功时,使用相同的资源实例或集合对象解析promise,并使用来自服务器的数据进行更新。这使得在$routeProvider.when()的解析部分中使用它很容易推迟视图渲染,直到资源被加载。
失败时,使用http response对象拒绝承诺,但没有资源属性。
如果提供了拦截器对象,则将使用拦截器返回的值来解析promise。
答案 1 :(得分:1)
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
并在then
的返回值(现在是一个承诺)上调用myService.postQuestion
函数:
myService.postQuestion(newQuestion, 1).then(function(){
$scope.showNewQuestion = false;
$location.path("/");
});