【问题标题】:Syncronization with angularjs $http function与 angularjs $http 函数同步
【发布时间】:2015-03-01 17:32:31
【问题描述】:

我是 angularjs 的新手,我有一个非常小的应用程序可以从我的服务器加载联系人。这里的代码 sn -p 就是完整的 app.js。 问题是我无法弄清楚如何使用同步进行服务器调用。在代码 sn-p 中,当我刷新页面时,显示警报 3,然后显示警报 2,最后显示警报 4。由于服务器 http 调用需要一些时间,因此该函数立即返回。所以我在浏览器中得到的是数组“联系人”中 2 个测试项的显示。警报 4 终于出现了,但为时已晚。任何帮助将不胜感激。

var module = angular.module('app', []);

module.service('ContactService', function ($http) {

    //contacts array to hold list of all contacts - 2 entries for test

    //var $contacts = [];
    var contacts = [
        {
        id: 0,
        'First_Name': 'Harmon',
        'Last_Name': 'Adams',
        'Home_Phone': '123-2343-44'
        },
        {
            id: 1,
            'First_Name': 'Sam',
            'Last_Name': 'Spade',
            'Home_Phone': '123-2343-44'
        }
    ];

    // returns the contacts list
    this.list = function () {
    //    var contacts = [];
        $http.post('http://localhost/Contacts7/GetData.php', {'cat' : 'Friends'}).
            success(function(data)  {
                contacts =  data.datarecords;
                alert('4 - within $post - '+contacts);
            }).
            error(function(data, status){
                alert('error!');
            });
        alert('3 - before return - '+contacts);
        return contacts;
    }
});

module.controller('ContactController', function ($scope, ContactService ) {
    $scope.contacts = ContactService.list();
    alert('2 - after list - '+ $scope.contacts);
});
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
    <title>Contact Dialer </title>
    <link rel="stylesheet" href="css/bootstrap.min.css">
    <link href="css/style.css" rel="stylesheet">
</head>
<body>
<div ng-app="app" ng-controller="ContactController">

    <div class="container" >
    <div class="row row-centered">
        <div class="col-md-2 button-row col-centered">
            <button type="button" class="btn btn-Primary btn-l btn-block" ng-click="GetByCat('Favorites')">Favorites</button>
        </div>
        <div class="col-md-2 button-row col-centered">
            <button type="button" class="btn btn-Primary btn-l btn-block" ng-click="GetByCat('Friends')">Friends</button>
        </div>
        <div class="col-md-2 button-row col-centered">
            <button type="button" class="btn btn-Primary btn-l btn-block" ng-click="GetByCat('Loose Friends')">Loose Friends</button>
        </div>
        <div class="col-md-2 button-row col-centered">
            <button type="button" class="btn btn-Primary btn-l btn-block" ng-click="GetByCat('Loose_Loose Friends')">Loose-Loose Friends</button>
        </div>
        <div class="col-md-2 button-row col-centered">
            <button type="button" class="btn btn-Primary btn-l btn-block" ng-click="GetByCat('Business')">Business</button>
        </div>
        <div class="col-md-2 button-row">
        </div>
    </div>
        {{xxx}}
        <table class='table table-striped table-bordered'>
            <th class = 'text-center'>Name</th>
            <th class = 'text-center'>Home Phone</th>
            <th class = 'text-center'>Mobile Phone</th>
            <th class = 'text-center'>Bus. Phone</th>
            </tr>
            <tr ng-repeat='contact in contacts'>
                <th class = 'text-center' >{{contact.Last_Name}}, {{contact.First_Name}}</th>
                <td class = 'text-center'>{{contact.Home_Phone}}</td>
                <td class = 'text-center'>{{contact.Mobile_Phone}}</td>
                <td class = 'text-center'>{{contact.Business_Phone}}</td>
            </tr>
        </table></div>
    </div>
<script src="js/jquery-1.11.0.min.js"></script>
<script src="js/underscore-min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="js/angular.min.js"></script>
<script src="js/angular-route.min.js"></script>
<script src="js/app.js"></script>
</body>
</h

【问题讨论】:

    标签: angularjs http asynchronous promise


    【解决方案1】:

    您无法从服务返回contacts,因为将异步确定联系人。相反,您需要为联系人返回一个 promise,您可以使用它在完成检索时填充控制器的联系人。

    服务:

    module.service('ContactService', ['$http', function ($http) {
        return {
            list: function () {
                return $http.post('http://localhost/Contacts7/GetData.php', 
                                  {'cat' : 'Friends'})
                .then(function (response) {
                    return response.data.datarecords;
                })
                .catch(function (error) {
                    throw new Error("Failed to retrieve contacts!");
                });
            }
        };
    }]);
    

    注意 你可能已经注意到我将第一行从使用魔术依赖注入样式更改为使用数组样式依赖注入。这只是我个人的偏好(因为我认为魔法 DI 风格是个坏主意),而不是你必须做的事情。下面的代码也是如此。

    控制器:

    module.controller('ContactController', ['$scope', 'ContactService',
                                            function ($scope, ContactService ) {
        $scope.contacts = [];
        ContactService.list()
        .then(function (contacts) {
            $scope.contacts = contacts;
            alert('2 - after list - '+ $scope.contacts);
        });
    }]);
    

    【讨论】:

    • 这个答案很好,但是你为什么把他的DI语法改成数组语法呢?
    • @BenjaminGruenbaum 因为使用神奇的 DI 语法是 antipractice
    • 是的,但以我的拙见,最好不要对 OP 的代码进行主观更改 - 过去曾建议过几个 Angular 研讨会,我会说它们在使用数组的人之间大致平均分配语法和使用 ng-min 的人(现在是 ng-annotate)。我绝对不会将其称为“语言滥用”或反模式本身——毕竟所有缩小器都在为自己提供工具并且不是“高于框架”——当缩小器对这里不可行的源代码做出假设时,缩小器有错.
    • 公平地说,您完全有权在您的答案中推广您喜欢的任何做法 - 但 Function#toString 是语言规范 (15.3.4.2) 的一部分,并且正在更改 Function.prototype.toString就像更改 Function.prototype.apply 一样糟糕,这基本上破坏了现代 JS 引擎中的所有内容。我知道的大多数其他语言也可以让您获得参数名称:C#、Java (8)、Python、Ruby 以及最现代的高级语言。我想我只是不同意这是一个漏洞:缩小器是那些跳过箍但又一次 - 你有权享受你最喜欢的做法:)
    • @BenjaminGruenbaum 如果 JavaScript 提供了一个干净的机制来获取参数名称(而且几乎令人惊讶的是它没有提供),那么我会加入魔法 DI。 .toString() 方法对我来说似乎太老套了(尽管您可能是对的,我的担忧是没有根据的)。 C# 的nameof() 仍处于测试阶段。 JS 很可能很快就会得到类似的东西,如果发生这种情况并且魔法 DI 被更新以使用它,它将获得我梦寐以求的批准印章,这将轮到缩小器与被认为可以接受的用途保持一致。
    【解决方案2】:

    不要从外部 ajax 返回联系人对象。 它应该从其成功回调中返回联系人对象。

    // returns the contacts list
    this.list = function () {
    //    var contacts = [];
    $http.post('http://localhost/Contacts7/GetData.php', {'cat' : 'Friends'}).then(
    //success call back
    function(data)  {
        contacts =  data.datarecords;
        alert('4 - within $post - '+contacts);
        return contacts;
    },
    //error call back
    function(data, status){
        //error handling can be done here
        alert('error!');
        return;
    });
    

    希望这对您有所帮助。

    【讨论】:

      猜你喜欢
      • 2021-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-22
      • 1970-01-01
      相关资源
      最近更新 更多