【问题标题】:How to consume an AJAX JSON response in AngularJS?如何在 AngularJS 中使用 AJAX JSON 响应?
【发布时间】:2016-01-07 20:03:59
【问题描述】:

AngularJS 应用程序需要从 Spring Boot 后端调用的 REST 服务中检索 JSON 对象。如何修改下面的代码,以便将响应解析为返回的 JSON 对象的属性?

例如,我想在 JSON 对象返回后提取 firstnamelastname 和其他属性。

这里是调用 REST 服务的 AngularJS 控制器:

angular.module('confirm', []).controller('confirm', function($scope, $http, $routeParams) {

     // set the default value
    $scope.confirmStatus = "blank";

    $scope.$on('$viewContentLoaded', function() {

        var str1 = "/confirm-email?d=";
        var str2 = $routeParams.d;
        var res = str1.concat(str2);
        var fnm3 = "nothing";
        $http.post(res).then(function(response) {
            fnm3 = response.data.firstname;//this line halts the program
            //replacing with following line doesn't work.
            //$scope.weblead = response.data;
        });
        $scope.confirmStatus = "success";
        document.write(fnm3);
    });
});

这里是传递 JSON 响应的 Spring Boot 方法:

@RequestMapping(value = "/confirm-email", method = RequestMethod.POST)
public @ResponseBody WebLead confirmEmail(HttpSession session, @RequestParam(value="d") String dval) {
    WebLead dummy = new WebLead();dummy.setFirstname("justAtest");
    try{
        System.out.println("The Server Heard The registration form Request!");
        System.out.println("dval is: "+dval);       
        String sid = session.getId();
        System.out.println("session id is: "+sid);
        try{
            List<WebLead> wleads = myrepo.findBySessionid(dval);
            if(wleads.size()>0){//replace with better handling later
                System.out.println("wleads.size is > 0 !");
                wleads.get(0).setEmailConfirmed("true");
                myrepo.save(wleads.get(0));
                return myrepo.findBySessionid(dval).get(0);
            }
            return dummy;
        } catch(Exception e){return dummy;}
    } catch(Exception e){return dummy;}
}    

注意:我们知道帖子是在服务器上处理的,因为/confirm-email处理程序中以SYSO开头的终端日志是:

The Server Heard The registration form Request!
dval is: a1b2c3
session id is: E1F844262F254E9B0525504723DBA490
2016-01-07 12:11:49.773 DEBUG 7288 --- [nio-9000-exec-9] w.c.HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2016-01-07 12:11:49.774 DEBUG 7288 --- [nio-9000-exec-9] tRepository$SaveToSessionResponseWrapper : Skip invoking on
2016-01-07 12:11:49.774 DEBUG 7288 --- [nio-9000-exec-9] tRepository$SaveToSessionResponseWrapper : Skip invoking on
2016-01-07 12:11:49.774 DEBUG 7288 --- [nio-9000-exec-9] o.s.s.w.a.ExceptionTranslationFilter     : Chain processed normally
2016-01-07 12:11:49.774 DEBUG 7288 --- [nio-9000-exec-9] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed

【问题讨论】:

  • 网络服务返回的 JSON 是什么?
  • @Dan 我不确定,因为console.log(response) 没有返回任何内容。程序在该行的断点之前冻结,但终端日志显示调用了服务器端方法。
  • (专业提示:元注释在这里的问题中通常不太合适。没有接受答案的问题默认被视为未得到满意回答。如果您想澄清一个问题,然后尽一切办法 (a) 在您的帖子的末尾添加一个澄清,解释可能出现的误解,(b) 尽量不要暗示读者已经猜到或垃圾邮件 - 大多数人只是试图提供帮助,(c) 避免投票评论 - 大多数读者不感兴趣,甚至不登录)。

标签: javascript angularjs json ajax spring


【解决方案1】:

您可以使用JSON.parse(jsonData)。这是一个可以帮助您实现目标的示例。

$http.post(res).then(function(response) {
    $scope.data = JSON.parse(response.data);
    fnm3 = $scope.data.firstname;
});

另外,当我使用我拥有的 REST 服务时,我喜欢在调试时将控制台日志放入函数中,然后在完成之前将它们删除。这让您可以轻松查看服务为您带来的回报。

$http.post(res).then(function(response) {
    console.log(response);
});

【讨论】:

  • $http 自动将响应转换为 JSON。 docs.angularjs.org/api/ng/service/$http
  • 您的任何建议都不会改变我的 OP 末尾的 NOTE 中显示的终端日志。此外,在 FireFox 调试器中的 console.log(response); 行添加断点不会产生任何结果,因为程序显然在服务器端 SYSO 和能够解析响应的客户端之间的某个点锁定。
【解决方案2】:

首先,我不建议在使用 Angular 进行请求时使用参数构建自己的字符串。你可以简单地做这样的事情:

$http({
    method: 'POST',
    url: '/confirm-email',
    headers: {
        'Content-Type': 'application/json'
    },
    params: {
        d: $routeParams.d
    }
}).then(function(response) {
    ...
});

其次,如果您将上面的内容类型标头放入“application/json”,并且如果服务器支持它,那么 Angular 将自动 JSON.parse 您的数据,并简单地将 javascript 对象作为 response.data 返回给您。

第三个也是最后一个问题是你的内容永远不会在你的代码中显示给定的数据,因为 POST 调用是异步的,但是在触发请求后立即 document.write 变量 fnm3 的内容。

您有两种选择来解决此问题:

  1. (快速、简单,但不好)做第二个文档。在您的后请求回调中写入
  2. (正确的方法)改为在 angular-scope 上定义您的值:

    $scope.fnm3 = response.data.firstname;

并定义一个相应的模板来做一些有角度的双向绑定魔术,比如:

Firstname: {{ fnm3 }}

【讨论】:

  • 您的第二个建议涉及更改服务器代码。我已经在我的 OP 中给出了服务器代码。你能展示如何根据特定语法来改变它吗?另外,请澄清一下,您的第三个建议是在 html 视图中写 Firstname: {{ fnm3 }} 吗?
  • 你也可以尝试在客户端设置content-type,只是服务器是否支持的问题。但是您可以尝试一下,我将相应地更改上面的代码。第三个建议正是这个意思,是的。将其放在相应的 html 视图中并将 fnm3 变量放在 $scope 变量上,而不仅仅是函数中的匿名变量
  • 将 http 帖子更改为您的建议确实会导致调用服务器方法并返回我的 OP 末尾的 NOTE 中显示的相同 SYSO。但是,在返回任何内容之前程序仍会冻结。 Firefox 调试器控制台不打印任何内容。在终端在我的 OP 中的 NOTE 中显示服务器端 SYSO 后,Firefox 就会冻结。这是我使用您的代码所做的更改:$http({method: 'POST', url: '/confirm-email', headers: {'Content-Type': 'application/json'}, params: {d: $routeParams.d} }).then(function(response) {console.log(response);});
  • 当我按如下方式远程console.log(response) 时,它甚至会冻结:then(function(response) {/*console.log(response);*/});。我还能发布什么来帮助隔离解决方案?
  • 我现在很确定问题完全出在服务器端。客户端代码看起来不错,应该是正确的。不幸的是,我无法在服务器部分为您提供帮助,因为我对所使用的技术不够坚定,抱歉。
【解决方案3】:

为了编写更少的代码和更高的效率以及为了使调用服务的可重用性(因为您在多个页面中调用服务),请使用以下代码:

App.service("metaService", function ($http,$cookies) {  

    this.CallService = function (verb, serviceName, Data) {

    var Url = BaseURL + serviceName;

    switch (verb) {

        case "get":
            {
                return $http({
                    method: verb,
                    url: Url
                    , headers: {
                        'Content-Type': 'application/json; charset=UTF-8',
                        'Accept': '*/*',
                    }
                });
                break;
            }
        case "post":
        case "put":
        case "delete":
            {
                return $http({
                    method: verb,
                    url: Url,
                    data: Data
                   , headers: {
                       'Content-Type': 'application/json; charset=UTF-8',
                       'Accept': '*/*',
                   }
                });
                break;
            }
    }
}

});

那么你可以像这样调用callservice方法

 var SearchData = metaService.CallService1(method, "meta/selectAll", searchedMeta);
          SearchData.success(function (data) {

    $scope.Title = data.Title
}

【讨论】:

  • OP 指定 POST,并询问来自 POST 的特定结果。您在此处发布的一般性评论似乎偏离主题,并且比 OP 添加了更多代码。您对导致 OP 中的问题有什么具体建议吗?
猜你喜欢
  • 2019-02-19
  • 1970-01-01
  • 1970-01-01
  • 2021-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多