zoukankan      html  css  js  c++  java
  • 【给你一个承诺

    了解Promise


    在谈论Promise之前我们要了解一下一些额外的知识;我们知道JavaScript语言的执行环境是“单线程”,所谓单线程,就是一次只能够执行一个任务,如果有多个任务的话就要排队,前面一个任务完成后才可以继续下一个任务。

    这种“单线程”的好处就是实现起来比较简单,容易操作;坏处就是容易造成阻塞,因为队列中如果有一个任务耗时比较长,那么后面的任务都无法快速执行,或导致页面卡在某个状态上,给用户的体验很差。

    当然JavaScript提供了“异步模式”去解决上述的问题,关于“异步模式”JavaScript提供了一些实现的方法。

    • 回调函数(callbacks)
    • 事件监听
    • Promise对象

    关于回调函数,大家应该都不陌生,比如下面的代码(注:引用Leancloud上面的一点代码):

        AV.User.logIn("myname", "mypass", {
                success: function(user) {
                // Do stuff after successful login.
                },
                error: function(user, error) {
                // The login failed. Check error to see why.
                 }
        }); 

    用户通过用户名和密码来进行登录,如果登陆成功的话,会在success这个模块进行处理,如果登陆失败的话,就会在error这个模块进行处理。

    当我们需要处理的任务不是很多的情况下,使用回调函数还是可以应付的,也没有太大的问题,但是当我们需要处理的任务比较多的时候,使用回调函数的弊端越来越明显了;首先,回调使得调用不一致,得不到保证;当依赖于其它回调时,它们篡改代码的流程,是调试变得异常艰难,每一步调用之后都需要显式的处理错误;最后,过多的回调使得代码的可读性和可维护性都变得很差,所以越来越多的程序员选择使用Promise去处理异步模式。

    关于Promise我们会在下面进行详细的说明。

    Promise是什么


    Promise是一种异步方式处理值(或者非值)的方法,promise是对象,代表了一个函数最终可能的返回值或者抛出的异常。

    在与远程对象打交道时,Promise会非常有用,可以把它们看作远程对象的一个代理。

    使用Promise的理由


    • 使用Promise可以让我们逃脱回调地狱,使我们的代码看起来像是同步的那样。
    • 可以在程序中的任何位置捕捉错误,并且绕过依赖于程序异常的的后续代码,获得功能组合和错误冒泡的能力,最重要的是保持了异步运行的能力。
    • 使我们的代码的可读性与可维护性都变得很好。

    如何在AngularJS中使用Promise


    要在AngularJS中使用Promise,要使用AngularJS的内置服务$q

    • $q服务受到Kris Kowal的Q库的启发,所以类似于那个库,但是并没有包含那个库的所用功能。
    • $q是跟AngularJS$rootScope模板集成的,所以在AngularJS中执行和拒绝都很快。
    • $q promise是跟AngularJS模板引擎集成的,这意味着在视图中找到任何Promise都会在视图中被执行或者拒绝。

    我们可以先使用$qdefer()方法创建一个deferred对象,然后通过deferred对象的promise属性,将这个对象变成一个promise对象;这个deferred对象还提供了三个方法,分别是resolve(),reject(),notify()

    下面我们来通过代码逐步地将上面的功能都实现,毕竟说得再多,不如你实实在在地把它们敲成代码去实现。

    Test1


    我们先通过一个同步的例子来创建一个promise对象。

    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>promise</title>
        <script type="text/javascript" src="//cdn.bootcss.com/angular.js/1.5.8/angular.min.js"></script>
        <script type="text/javascript" src="//cdn.bootcss.com/angular.js/1.5.8/angular-route.min.js"></script>
        <script>
            angular.module("myApp",[])
                .controller("myController",["$scope","$q",function($scope,$q){
                    $scope.flag=true;
                    $scope.handle=function(){
                        var deferred=$q.defer();
                        var promise=deferred.promise;
                        promise.then(function(result){
                            alert("成功:"+result);
                        },function(error){
                            alert("失败:"+error);
                        });
                        if($scope.flag){
                            deferred.resolve("you are lucky!");
                        }else{
                            deferred.reject("sorry,it lost!");
                        }
                    }
                }])
        </script>
    </head>
    <body>
        <div ng-app="myApp">
            <div ng-controller="myController">
                <label for="flag">成功
                <input type="checkbox" id="flag" ng-model="flag"><br>
                </label>
                <hr>
                <button ng-click="handle()">点击我</button>
            </div>
        </div>
    </body>
    </html>
    

    效果演示:http://jsfiddle.net/gwfqga6m/

    通过使用then进行链式请求


    我们通过使用then方法来进行链式调用,这样做的好处是,无论前一个任务或者说then函数是被执行或者拒绝了都不会影响后面的then函数的运行。

    我们可以通过then创建一个执行链,它允许我们中断基于更多功能的应用流程,可以借此导向不同的的结果,这个中断可以让我们在执行链的任意时刻暂停后者推迟promise的执行。

    Test2

    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>promise</title>
        <script type="text/javascript" src="//cdn.bootcss.com/angular.js/1.5.8/angular.min.js"></script>
        <script type="text/javascript" src="//cdn.bootcss.com/angular.js/1.5.8/angular-route.min.js"></script>
        <script>
            angular.module("MyApp", [])
                    .controller("MyController", ["$scope", "$q", function ($scope, $q) {
                        $scope.flag = true;
                        $scope.handle = function () {
                            var deferred = $q.defer();
                            var promise = deferred.promise;
    
                            promise.then(function (result) {
                                result = result + "you have passed the first then()";
                                $scope.status = result;
                                return result;
                            }, function (error) {
                                error = error + "failed but you have passed the first then()";
                                $scope.status = error;
                                return error;
                            }).then(function (result) {
                                alert("Success: " + result);
                            }, function (error) {
                                alert("Fail: " + error);
                            })
    
                            if ($scope.flag) {
                                deferred.resolve("you are lucky!");
                            } else {
                                deferred.reject("sorry, it lost!");
                            }
                        }
                    }]);
        </script>
    </head>
    <body>
        <div ng-app="MyApp">
            <div ng-controller="MyController">
                <label for="flag">成功
                    <input id="flag" type="checkbox" ng-model="flag" />
                    <br/>
                </label>
                <div ng-cloak>
                    {{status}}
                </div>
                <hr/>
                <button ng-click="handle()">点击我</button>
            </div>
        </div>
    </body>
    </html>
    

      

    效果演示:http://jsfiddle.net/gwfqga6m/1/

    我们在Part1代码的基础上添加了一些代码,在原来的promise的链条上新添加了一个then()处理函数,目的就是为了创建一个执行连,看看在这条执行连上,promise是如何被执行的。

    需要注意的一点是,在第一个then()方法中,我们在第一个successFunc函数中将result的值进行了改变,在第二个errorFunc函数中对error的值也进行了改变。

    因为这个promise对象是贯穿整个执行链条的,所以在第一个then()方法中对其值进行改变必然会反映到后面的then()方法中

      


    (未完待续...................................................................)

  • 相关阅读:
    适配器
    策略
    oom的各种情况
    sql 优化//TODO
    聚簇索引和非聚簇索引
    Shard内部原理
    es集群健康状态
    转载 R语言颜色基础设置
    三维数据的展示
    python 文件保存 出错
  • 原文地址:https://www.cnblogs.com/yanxinhua/p/AngularJs.html
Copyright © 2011-2022 走看看