问题 AngularJS with ngResource:如何检查来自服务器的确切响应?


我已经创建了一个角度服务来与PHP制作的简单REST服务器进行对话。我可以看到我能够获得单个记录,所有记录的列表,并添加新记录,但是,在添加新记录后,我遇到了从服务器获取正确响应以便能够对其进行操作的问题。

我知道它正在工作,因为新记录正在添加,但是,如果由于某种原因请求不起作用,我希望为用户发送通知,等等......

这是服务:

angular.module('adminApp.services', ['ngResource'])

    .factory('Settings', function($resource) {

        return $resource('rest/setting/:id', {id: '@id'}, {
            'query' : { method: 'GET', params: {}, format: 'json', isArray: true },
            'save'  : { method: 'POST', params: {}, format: 'json', isArray: true },
            'get'   : { method: 'GET', params: {}, format: 'json', isArray: false },
            'update': { method: 'PUT', params: {id: '@id'}, format: 'json', isArray: true },
            'delete': { method: 'DELETE', params: {id: '@id'}, format: 'json', isArray: false }
    });

});

作为控制器的一部分,我有以下内容:

$scope.save = function() {
    var result = Settings.save({}, $scope.settings);

    console.log(result);

    // Here I would like to send the result to the dialog
    // to determine wether or not the request was successful
    // dialog.close(result);
};

来自HTTP请求的网络响应,通过javascript控制台返回从服务器返回的'true',但是,console.log(result)返回'true'中的字符数组 - 我猜对了是因为'save'中的isArray:true选项是必要的,因为params作为数组被发送到服务器:

[$promise: Object, $resolved: false]
    0: "t",
    1: "r",
    2: "u",
    3: "e",
    $promise: Object,

    // I tried passing result.$resolved to the dialog,
    // but if yousee above it resolves to false up top first
    $resolved: true,
    length: 4,
    __proto__: Array[0]

我知道HTTP响应是一个json值为true,如果我可以挂钩它会很容易(我来自jQuery背景,也许我做错了,我已经明确地从这里删除了jQuery)项目,以免它阻止我的学习)。

我想问题是,我如何从服务器实际获得我可以实际使用的JS变量的响应?

编辑:已更新

我将服务改为:

angular.module('adminApp.services', ['ngResource'])
    .factory('Settings', function($http, $resource, $log) {
        return $resource('rest/setting/:id', {id: '@id'}, {
            save   : {
            method: 'POST',
            params: {},
            format: 'json',
            isArray: true,
            transformResponse: [function(data, headersGetter) {
                $log.info(data); // returns true
                return { response: data };
            }].concat($http.defaults.transformResponse)
        },
        update : { method: 'PUT', params: {id: '@id'}, format: 'json', isArray: true },
        delete : { method: 'DELETE', params: {id: '@id'}, format: 'json', isArray: false }
    });

});

并呼吁:

$scope.save = function() {
    $scope.results = Settings.save({}, $scope.settings);
    console.log($scope.results); // Still returns the response with $promise
    //dialog.close(true);
};

但我仍然没有得到回应


6626
2017-07-02 04:42


起源

我希望我理解这个问题。尝试添加两个回调到您的 Settings.save 呼叫。它们分别是成功和失败的回调。看这里: docs.angularjs.org/api/ngResource.$resource。我想你可以显示你第二次回调的错误代码。 - akonsu
我很确定你不需要isArray将发送的数据作为一个数组,它只是修改了返回值的解释 docs.angularjs.org/api/ngResource.$resource - shaunhusain
@shaunhusain当我有isArray:false时我会得到一个错误,通知推送变量不可用,一些谷歌搜索显示这是通过添加isArray:true来修复的。 - francisco.preller
@akonsu我不确定如何添加回调,我会在服务中添加吗?如果是这样,我在哪里添加它?它只是回调:function()作为save的附加参数吗? - francisco.preller
我的意思是这样的: Settings.save({}, $scope.settings, function () {...}, function (error) {...}) - akonsu


答案:


看到这个小提琴: http://jsfiddle.net/moderndegree/Kn3Tc/

angular.module('myApp', ['ngResource']).
factory('myService', function($http, $resource, $log){
    return $resource('/', {}, {
        get: {
            method: 'GET',
            transformRequest: [function(data, headersGetter){
                // you can examine the raw request in here
                $log.info(data);
                $log.info(headersGetter());
            }].concat($http.defaults.transformRequest),
            transformResponse: [function (data, headersGetter) {
                // you can examine the raw response in here
                $log.info(data);
                $log.info(headersGetter());
                return {tada:"Check your console"};
            }].concat($http.defaults.transformResponse)
        }
    });
}).
controller('myController', function(myService, $scope, $resource, $http, $log) {
    $scope.results = myService.get();
});

要全局扩充或覆盖默认转换,请修改   $ httpProvider.defaults.transformRequest和   $ httpProvider.defaults.transformResponse属性。

在这里阅读更多: http://docs.angularjs.org/api/ng。$ HTTP


13
2017-07-02 04:51



啊这很酷,所以这允许客户端的“拦截器”之类的东西? - shaunhusain
正确。如果您想要一个全局拦截器,可以将它添加到应用程序配置中的$ httpProvider。 - Brian Lewis
我试着用你的小提琴试着修改我的答案,但仍然有问题。请你看看并发表评论吗?我必须做错事,因为我没有在控制器端获得转换后的响应。 - francisco.preller
@francisco.preller它将始终返回一个promise响应。你为什么不这么想?这是一个异步操作。 transforResponse 等等只是回调,你将在这些回调中获得原始数据。 - akonsu
@akonsu也许我错了,但上面的小提琴设法用“tada”键和一个值的字符串将响应转换为一个对象,然后用他的控制器获取它。我正在尝试做同样的事情,而且我得到的结果并不像他的小提琴那样。 - francisco.preller


嗨,我知道它太晚了但可能对其他人有帮助, 将响应转换为数组的原因是,angular-resource期望“data”属性作为响应,之后它迭代“data”中的每个项目,但是如果你从服务器发送数据属性中的字符串,就像这样

response = {
    data: true
    }

然后Angular-resource迭代“data”对象并生成一个数据数组,正确的方法是发送响应就像这样

response = {
    data: {users: users} // Or any other property but not directly data
    }

谢谢


0
2017-07-03 10:28