angularJS promise $q

时间:2022-06-08 10:05:13
Promise
一 介绍
1.什么是promise
我们知道JavaScript语言的执行环境是“单线程”,所谓单线程,就是一次只能够执行一个任务,如果有多个任务的话就要排队,前面一个任务完成后才可以继续下一个任务。
这种“单线程”的好处就是实现起来比较简单,容易操作;坏处就是容易造成阻塞,因为队列中如果有一个任务耗时比较长,那么后面的任务都无法快速执行,或导致页面卡在某个状态上,给用户的体验很差。
当然JavaScript提供了“异步模式”去解决上述的问题,关于“异步模式”JavaScript提供了一些实现的方法:回调函数(callbacks)、事件监听、Promise对象。callback是最最简单的机制,可是用这种机制的话必须牺牲控制流、异常处理和函数语义化为代价,甚至会让我们掉进出现callback大坑,而promise解决了这个问题。
2.Promise是一种异步方式处理值(或者非值)的方法,promise是对象,代表了一个函数最终可能的返回值或者抛出的异常。
在与远程对象打交道时,Promise会非常有用,可以把它们看作远程对象的一个代理。
优点:使
用了promise的收获之一是逃脱了回调的固定思维逻辑。promise让异步处理的机制看上去更像是同步,基于同步函数我们可以按照预期来捕获返回值
和异常值。可以在程序中的任何时刻捕捉错误,并且绕过依赖于程序异常的后续代码,我们不需要思考这个同步带来的好处。因此使用promise的目的是:获
取功能组合和错误冒泡能力的同时,保持代码异步运行的能力。
二 使用
1.想要在angularjs中创建promise,可以使用内置的$q服务,$q服务在它的deferred API中提供了一些方法。

们可以先使用$q的defer()方法创建一个deferred对象,然后通过deferred对象的promise属性,将这个对象变成一个
promise对象;这个deferred对象还提供了三个方法,分别是resolve(),reject(),notify()。
2.先了解一下任务的状态
每个任务都有三种状态:未完成(pending)、完成(fulfilled)、失败(rejected)。
pending状态:可以过渡到履行或拒绝状态。
fulfilled状态:不能变为其他任何状态,而且状态不能改变,必须有value值。
rejected状态:不能变为其他任何状态,而且状态不能改变,必须有reason。
3.deffered对象
(1)deffered 对象的方法
resolve(value):resolve函数用这个值来执行deferred promise,在声明resolve()处,表明promise对象由pending状态转变为resolve。
reject(reason):它等同于使用一个“拒绝”来执行一个promise,在声明resolve()处,表明promise对象由pending状态转变为rejected。
notify(value) :在声明notify()处,表明promise对象unfulfilled状态,在resolve或reject之前可以被多次调用。
(2)deffered 对象属性
promise :最后返回的是一个新的deferred对象 promise 属性,而不是原来的deferred对象。这个新的Promise对象只能观察原来Promise对象的状态,而无法修改deferred对象的内在状态可以防止任务状态被外部修改。
4.promise对象
promise对象的方法
(1)then(successFunc,
errorFunc,
notifyFunc):无论promise是成功了还是失败了,当结果可用之后,then都会立刻异步调用successFunc,或者
'errorFunc',在promise被执行或者拒绝之前,notifyFunc可能会被调用0到多次,以提供过程状态的提示。
(2)catch(errorCallback) —— promise.then(null, errorCallback) 的快捷方式
(3)finally(callback) ——让你可以观察到一个 promise 是被执行还是被拒绝, 但这样做不用修改最后的 value值。 这可以用来做一些释放资源或者清理无用对象的工作,不管promise 被拒绝还是解决。
5.举例
HTML部分:
<div ng-app="MyApp">
    <div ng-controller="MyController">
        <label for="flag">成功
        <input id="flag" type="checkbox" ng-model="flag" /><br/>
        </label>
        <hr/>
        <button ng-click="handle()">点击我</button>
    </div>
</div>
JS部分:
angular.module("MyApp", [])
.controller("MyController", ["$scope", "$q", function ($scope, $q) {
            $scope.flag = true;
            $scope.handle = function () {
            var deferred = $q.defer();  //创建deferred对象
            var promise = deferred.promise;   //创建promise对象

promise.then(function (result) {  //then方法传递两个处理函数
                alert("Success: " + result);  //promise被执行时进行
            }, function (error) {  //promise被拒绝时进行
                alert("Fail: " + error);
            });

if ($scope.flag) {
                deferred.resolve("you are lucky!");  //给promise传值
            } else {
                deferred.reject("sorry, it lost!");
            }
        }
}]);


果异步操作成功,则用resolve方法将Promise对象的状态变为“成功”(即从pending变为resolved);如果异步操作失败,则用
reject方法将状态变为“失败”(即从pending变为rejected)。最后返回 deferred.promise
,我们就可以链式调用then方法。
再来一个小例子:
var ngApp=angular.module('ngApp',[]);
ngApp.factory('UserInfoService',['$http','$q',function($http,$q){
    return{
       query:function(){
        var defer=$q.defer();  //声明延后执行
        $http({method:'GET',url:'data/students.json'}).
        success(function(data,status,headers,config){
            defer.resolve(data);  //声明执行成功
            console.log('UserInfoService success');
        }).
        error(function(data,status,headers,config){
            defer.reject();      //声明执行失败
        });
                         
        return defer.promise; //返回承诺,返回获取数据的API
        }
        }
    }]);
             
    ngApp.controller('MainCtrl',['$scope','UserInfoService',function($scope,UserInfoService){
         var promise = UserInfoService.query();  //同步调用,获取承诺接口
        promise.then(function(data){
            $scope.user=data;  //调用承诺接口resolove()
            console.log('MainCtrl ...');
            },function(data){
              $scope.user={error:'数据不存在。。。'}; //调用承诺接口reject();
            });
                 
            }]);
6.使用then进行链式请求

promiseB = promiseA.then(function(result) {  
      return result + 1;  
    });  
  // promiseB 将会在处理完 promiseA 之后立刻被处理,  
  // 并且其  value值是promiseA的结果增加1