AngularJS Promise

来源:互联网 发布:opencv车流量统计算法 编辑:程序博客网 时间:2024/06/11 19:08

本文参考自AngularJS权威教程。
本文参考了http://www.myext.cn/javascript/a_6436.html

1. 简介

  promise是一种用异步方式处理值的方法。promise是一个对象,代表一个函数可能的返回值或者抛出的异常。在与远程对象打交道时,我们可以简单的把它看作远程对象的一个代理。
  我们通常习惯用回调来相应非同步的数据,但是回调使得调用不一致,当依赖于其他回调时,层次会越来越多,形成一个回调金字塔,通常这会让调试非常困难。

2.工作原理

  promise是一种异步处理机制,其工作原理如下图。
这里写图片描述
  在promise模式中,defer对象就相当于一个异步执行体,它用resolve()方法返回执行成功的消息,用reject()方法返回执行失败的消息。而promise对象就是一个回调执行体,我们可以在上面操纵接收到成功消息和失败消息分别做什么。

3.$q服务

  $q服务是AngularJS专门为promise异步编程模式而存在的,它有以下几个API。

  • defer()
    获取defer对象。
  • resolve(value)
    向promise对象发送消息,告诉它我已完成任务,value为发送的消息。
  • reject(value)
    向promise对象发送消息,告诉它任务失败,value为发送的消息。
  • notify(value)
    向promise对象发送消息,告诉它目前完成任务的进度,value即为发送的消息。

另外,promise对象即通过defer.promise获取,这两个对象成为一对,协作完成异步执行的任务。下面是promise的API。

  • then(successCallback,errorCallback,notifyCallback):参数即为不同消息下的不同回调函数,根据defer发送的状态执行相应的回调函数。
  • catch(errorCallback)
    then(null,errorCallback)的一个语法糖,一般放在链式调用的最后处理,如果不把error的信息用console log出来的话,console台是不会报错误的,加上catch并log出错误信息总是一个好习惯。
  • finally(callback)
    then(callback,callback)的语法糖,意思很直观,就是不管你任务成功还是失败都要完成的事情。

4.实例

  首先是一个简单的例子。在这个例子中,我们先是注册了一个自定义服务(XiaoMingService),这个服务调用了$http服务取本地服务器数据并返回该promise。注意,在这个例子中并没有涉及到defer(),因为它由$http完成。(配置本地服务器可用https://github.com/typicode/json-server)

<body ng-app="myApp" ng-controller="myController">    <ul>        <li ng-repeat="name in data">            {{ name }}        </li>    </ul>    <script>        var app = angular.module("myApp",['ionic']);        app.factory('XiaoMingService',['$http',function($http) {            return {                getPersonName:function() {                    var data = null;                    var promise = $http({                        method:"GET",                                           url:"http://localhost:3000/person"                    });                    return promise;                }            }        }]);        app.controller('myController',function($scope,XiaoMingService) {            $scope.data = [];            var promise = XiaoMingService.getPersonName();            promise.then(function(response) {                $scope.data = response.data;                },function(error) {                    console.log(error);                });        });    </script></body>

  接下来是关于一个链式调用逃离回调金字塔的例子。假设我们想获得著名国家领导人的列表,于是我们让小李去找数据,小李也不知道怎么获得,于是找小红,小红再找小明,小明找到数据后一层层的返回,小红小李分别在列表加上自己喜欢的领导人。
  我们注册三个Service,分别代表以上三人,同时定义两个复选框,选择是否信任小李和小红来模拟异步获取数据失败的处理,只要不信任小李和小红其中一个人,就不会拿到除了习近平以外的数据,并且演示了finally和catch的用处。

<body ng-app="myApp" >    <div ng-controller="myController">        <ul>            <li ng-repeat="name in data">                {{ name }}            </li>        </ul>        <p>{{ failReason }}</p>    </div>    <p>        信任小红<input type="checkbox" ng-model="trust1"/>        信任小李<input type="checkbox" ng-model="trust2"/>    </p>    <input type="button" value="查询" ng-click="getData()"/>    <script>        var app = angular.module("myApp",['ionic']);        app.factory('XiaoMingService',function($http) {            return {                getPersonName:function() {                    var data = null;                    var promise = $http({                        method:"GET",                        url:"http://localhost:3000/person"                    });                    return promise;                }            }        });        app.factory('XiaoHongService',function($rootScope,$q,$timeout) {            return {                getXiaoHongService:function(data) {                    var defer = $q.defer();                    \$timeout(function () {                        if($rootScope.trust1) {                            data.push("李克强");                            defer.resolve(data);                        }                        else {                            defer.reject("失败原因:小红不被信任");                        }                    },2000);                    return defer.promise;                }            }        });        app.factory('XiaoLiService',function($rootScope,$q,$timeout) {            return {                getXiaoLiService:function(data) {                    var defer = $q.defer();                    \$timeout(function () {                        if($rootScope.trust2) {                            data.push("奥巴马");                            defer.resolve(data);                        }                        else {                            defer.reject("失败原因:小李不被信任");                        }                    },2000);                    return defer.promise;                }            }        });        app.controller('myController',function($scope,$rootScope,XiaoMingService,XiaoHongService,XiaoLiService) {            $scope.data = [];            $rootScope.trust1 = true;            $rootScope.trust2 = true;            $scope.failReason = "";            $rootScope.getData = function() {                var promise = XiaoMingService.getPersonName();                promise                        .then(function(response){                            return XiaoHongService.getXiaoHongService(response.data);                        })                        .then(function(data) {                            return XiaoLiService.getXiaoLiService(data);                        })                        .then(function (data) {                            $scope.data = data;                        })                        .finally(function(data) {                            $scope.data.push("习近平");                        })                        .catch(function(error) {                            $scope.failReason = error;                        });            };        });    </script></body>

这里写图片描述 这里写图片描述

4 0