zoukankan      html  css  js  c++  java
  • Angularjs中的promise

    promise 是一种用异步方式处理值的方法,promise是对象,代表了一个函数最终可能的返回值或抛出的异常。在与远程对象打交道非常有用,可以把它们看成一个远程对象的代理。

    要在Angular中创建promise需要使用内置的$q服务。先用factory定义一个服务,注入$q服务。

    angular.module('readApp').factory('asyncService', [
        "$q", function ($q) {
             var myAsync=function(flag) {
                var deferred = $q.defer();
                if (flag) {
                    deferred.resolve("well done!");
                } else {
                    deferred.reject("lost!");
                }
                 return deferred.promise;
             }
            return {
                myAsync: myAsync
            };
        }
    ]);
    

     获得deferred的方法和jquery不同,但resolve和reject是一样的,最后返回的是promise属性,而不是promise方法。再看如何调用:

    angular.module('readApp').controller('testCtrl', ["$scope", "asyncService", function ($scope, asyncService) {
            $scope.flag = true;
            $scope.handle = function () {
                asyncService.myAsync($scope.flag).then(function (result) {
                    $scope.status = result;
                    return result;
                }, function (error) {
                    $scope.status = error;
                    return error;
                });
            }
        }])
    

    获取到服务后,调用then方法。then有三个参数,分别对应成功回调、失败回调和通知回调。这个和jquery是一致的

    <div  class="container">
        <label for="flag">成功
            <input type="checkbox" id="flag" ng-model="flag" name="name" /> <br />
            <div>{{status}}</div>
            <button ng-click="handle()">点击</button>
        </label>
    </div>
    <footer-n
    

    结果:  

    不同的是,Angular的promise没有公布jquery那么多方法,我们可以看一下deferred.promise这个属性,它是一个$$state对象。根据Promise/A规范,一个Promise只要具备一个then方法即可。

    注意到,Angular中的deferred有notify、reject、resolve三个主要方法和一个promise属性,而这个promise的原型连中包含了我们调用的then方法,then方法在执行完之后会派生一个新的promise,因此可以链式调用。没有done和fail,但是还提供了catch和finally方法。catch就相当于是error方法了。而finally方法就像强类型语言中的场景一样,当我们需要释放一个资源,或者是运行一些清理工作,不管promise是成功还是失败时,这个方法会很有用。要注意的是finally是ie中的一个保留字,需要下面这样调用:

    promise['finally'](function() {});
    

      

    除了defer()方法,$q还有all和when方法,all(promises)可以将多个promise合并成一个,但如果任意一个promise拒绝了,那么结果的promise也会拒绝。而when(value)方法把一个可能是值或者promise包装成一个$q promise。有了jQuery中的when,这两个方法不难理解。关于这三个方法的示例可以参考这篇博客:AngularJS 中的Promise --- $q服务详解

    Angular的$q的灵感是来自[Kris Kowal's Q],从官方的注释中可以看到

     * This is an implementation of promises/deferred objects inspired by
     * [Kris Kowal's Q](https://github.com/kriskowal/q).
      * $q can be used in two fashions --- one which is more similar to Kris Kowal's Q or jQuery's Deferred
      * implementations, and the other which resembles ES6 promises to some degree.
    

      支持两种风格,可以像Q库或者jQuery的deferred一样,也可以用ES6语法,文档给出了示例,也是就构造函数法来定义:

    var asyncGreet = function (name) {
                return $q(function (resolve, reject) {
                    console.log(resolve, reject);
                    setTimeout(function () {
                        if (name=="stone") {
                            resolve('Hello, ' + name + '!');
                        } else {
                            reject('Greeting ' + name + ' is not allowed.');
                        }
                    }, 1000);
                });
            };
    

      通知(notify/progress)回调还不支持这种写法。对比看,没太大差别。

      

    function asyncGreet(name) {
        var deferred = $q.defer();
        setTimeout(function() {
         deferred.notify('About to greet ' + name + '.');
         if (okToGreet(name)) {
            deferred.resolve('Hello, ' + name + '!');
          } else {
            deferred.reject('Greeting ' + name + ' is not allowed.');
          }
         }, 1000);
       return deferred.promise;
      }
    

     大致看下源码如何实现:

     Promise:

     

     

    function Promise() {
        this.$$state = { status: 0 };
      }
    
      extend(Promise.prototype, {
        then: function(onFulfilled, onRejected, progressBack) {
          if (isUndefined(onFulfilled) && isUndefined(onRejected) && isUndefined(progressBack)) {
            return this;
          }
          var result = new Deferred();
    
          this.$$state.pending = this.$$state.pending || [];
          this.$$state.pending.push([result, onFulfilled, onRejected, progressBack]);
          if (this.$$state.status > 0) scheduleProcessQueue(this.$$state);
    
          return result.promise;
        },
    
        "catch": function(callback) {
          return this.then(null, callback);
        },
    
        "finally": function(callback, progressBack) {
          return this.then(function(value) {
            return handleCallback(value, true, callback);
          }, function(error) {
            return handleCallback(error, false, callback);
          }, progressBack);
        }
      });
    

    创建了一个Promise对象包含一个$$state属性,然后扩展了then,catch,finally方法(注意后两个带了引号)。then的三个参数都是回调函数,对应成功、失败、通知回调,并在then方法中创建了一个deferred作为结果,将回调函数和创建的deferred都存入了数组,主意到这是一个二维数组,每个then对应的promise和回调函数都在这个数组里面。最后返回promise。而catch和finally内部也是调用的then。只要状态大于0也就promise获得了结果就用scheduleProcessQueue处理回调。 Deferred 内部包含了一个promise以及resolve、reject和notify三个方法。jQuery.deferred 中处理的是三个回调队列,Angular中处理的一个是二维数组。 

    $http的是一个promise对象:

    var promise = $q.when(config);
           //some code
           
            promise = promise.then(thenFn, rejectFn);
          }
          if (useLegacyPromise) {
            promise.success = function(fn) {
              assertArgFn(fn, 'fn');
              promise.then(function(response) {
                fn(response.data, response.status, response.headers, config);
              });
              return promise;
            };
            promise.error = function(fn) {
              assertArgFn(fn, 'fn');
    
              promise.then(null, function(response) {
                fn(response.data, response.status, response.headers, config);
              });
              return promise;
            };
          } else {
            promise.success = $httpMinErrLegacyFn('success');
            promise.error = $httpMinErrLegacyFn('error');
          }
    
          return promise;
    

    用then扩展了error和succes方法,因此我们可以这样使用:

    booksData.getbookById(bookid).success(function(data) {
                vm.book = data;
            }).error(function (e) {
                console.log(e);
                vm.message = "Sorry, something's gone wrong ";
            });
    

    $Interval也是一个promise对象。  

    AngularJS 中的Promise --- $q服务详解

    http://www.cnblogs.com/xing901022/p/4928147.html  

      

  • 相关阅读:
    mysql的增量备份与全备的脚本
    mysql5.7的密码
    mysql 修改root密码
    centos7上面安装MySQL
    centos7上开启路由转发
    python基础之3
    python基础之2
    深入浅出FPGA-2-让source insight 支持verilog HDL
    Verilog 1995 VS Verilog 2001
    环境搭建基础知识2(sublime text3中配置verilog语法高亮)
  • 原文地址:https://www.cnblogs.com/wupeng88/p/5811351.html
Copyright © 2011-2022 走看看