zoukankan      html  css  js  c++  java
  • angular学习笔记(二十八-附2)-$http,$resource中的promise对象

    下面这种promise的用法,我从第一篇$http笔记到$resource笔记中,一直都有用到:

    HttpREST.factory('cardResource',function($resource){
        return $resource('/card/user/:userID/:id',{userID:123,id:'@id'},{charge:{method:'POST',params:{charge:true},isArray:false}})
    });
    HttpREST.factory('httpCard',function($q,cardResource){
        return {
            getById:function(cardID){
                var defer = $q.defer();
                cardResource.get({id:cardID},function(data,headers){
                    defer.resolve(data);
                },function(data,headers){
                    defer.reject(data);
                });
                return defer.promise
            }
        }
    });
    $scope.card_1 = httpCard.getById(1);
      <span>{{card_1['name']}}</span>
      <span>{{card_1['amount']}}</span>

    这样做的目的很显然,由于后台返回数据需要时间,所以对card_1的赋值应该是异步的,所以getById方法返回的是一个promise,所以,card_1其实也是一个promise,我们把它打印出来可以看到:

    1.同步打印:(还不等到后台返回数据就打印)

    $scope.card_1 = httpCard.getById(1);
    console.log($scope.card_1);

    2.异步打印:(等到后台返回数据以后打印)

        $scope.card_1 = httpCard.getById(1);
        $scope.card_1.then(function(){console.log($scope.card_1)});

    可以看到,同步打印的card_1,它的$$v是undefined,因为后台还没有返回数据,但异步打印的card_1,它的$$v就是请求后返回的数据.

    问题就出现了,card_1只有一个$$v属性和一个then方法,它并没有name属性,也没有amount属性,但是在视图中,<span>{{card_1['name']}}</span>确实渲染了.虽然我没有看过源代码,但是可以推测,视图渲染card_1的时候,是使用了card_1的$$v对象来进行渲染的.所以访问card_1['name'],其实是访问了card_1的$$v['name'].

    那么,如果card_1发生变化的时候,又是怎么处理的呢? 我尝试了以下操作:

    $scope.updataCard = function(){
      $scope.card_1.name='工商银行';    //视图不会发生变化
      $scope.card_1.$save()            //card_1没有$save方法
    };

    发现直接操作card_1.name属性,虽然card_1的name属性确实发生了变化,但是,在视图中它并没有任何的变化.可见,视图对于promise对象,监测的依然是它的$$v对象的属性的变化,而它自己的属性变化是没有任何反应的.另外,card_1是promise对象,不是$resource返回的对象,card_1的$$v才是,所以,card_1当然也没有$save方法

    那么,如果我要更新card_1,修改card_1,到底应该怎么做的? 说到底,card_1的真身就是card_1的$$v对象,so,想要修改card_1,就要修改它的$$v对象:

    $scope.updataCard = function(){
      $scope.card_1.$$v.name='工商银行';
      $scope.card_1.$$v.$save();
    };

    这样做,视图就会被更新.但是这样做有一个问题,上面已经看到了,$$v对象是在请求已经得到响应,得到返回的数据的时候才有的,在没有得到响应前,$$v是undefined.所以,如果在还没有得到响应前就执行了updataCard函数,这段代码就会有问题.so,最好的方法是放在promise的then方法的回调函数的参数里:

        $scope.updataCard = function(){
            $scope.card_1.then(function(data){
                data.name='工商银行';
                data.$save()
            });
        };

    promise对象有一个then方法,then方法了接受三个回调,详细参考:http://www.cnblogs.com/liulangmao/p/3907571.html ,这里只写一个成功的回调,回调的参数data,也就是promise对象的$$v对象,then函数会在响应成功后被调用.所以,即便还没有得到响应就触发了updataCard方法,修改的操作还是会等到响应收到后才执行,这就是异步.

    注意,这里的card_1是直接通过$resource返回得到的promise,但如果是通过angular路由的resolve方法返回的对象,在resolve的时候已经取了promise对象的$$v对象,然后再注入到控制器中.这样得到的资源就不再是promise对象了,而已经是promise的$$v对象,后面都正常操作就可以了.

  • 相关阅读:
    POJ 2065 高斯消元求解问题
    HDU1045-Fire Net
    HDU1863-畅通工程
    POJ2524-Ubiquitous Religions
    POJ1064-Cable master
    POJ2456-Aggressive cows
    HDU1272-小希迷宫
    POJ1611-The Suspects
    HDU4496-D-City
    HDU1232-畅通工程
  • 原文地址:https://www.cnblogs.com/liulangmao/p/3907307.html
Copyright © 2011-2022 走看看