zoukankan      html  css  js  c++  java
  • JavaScript及其异步实现

    由于javascript本身是单线程模型,这里主要通过Callbacks,Listeners,Control Flow Libraries ,Promises四种方式来实现异步操作。
    Reference:
               1.http://sporto.github.io/blog/2012/12/09/callbacks-listeners-promises/
               2.http://www.cnblogs.com/scy251147/archive/2013/03/26/2981814.html

    一、Callbacks(函数回调)


    让我们首先以函数回调方式来开头,这种方式也是最基本,同时也是大家都知道的异步实现方法。
    现在我们有两个函数:Function1,Function2,调用顺序是先调用完Function1,然后调用Function2,如果Function1是一个耗时操作的话,那么Function2就被阻塞住了。
    所以在这里我们尝试使用异步试试:

    <script type="text/javascript">
        function ajaxRequest(container,callback)
        {
            $.ajax({
                url: "GetTitle",
                type: "post",
                success: function (data) {
                    container.append(data.message);
                    callback();
                }
            });
        }
    
        function Function1(callback) {
            setTimeout(function () {
                ajaxRequest($(".container"),callback);
            }, 1000);
        }
    
        function Function2()
        {
            $(".container").append("Function2执行完毕");
        }
    
        Function1(Function2);
    </script>
    <div class="container"></div>

    最后我们得到的结果是:

    程序先输出“Function1执行完毕”,然后再输出“Function2执行完毕”,符合预期。
    这样做的好处就是方便,但是坏处就是如果执行的函数过多的话,需要一层套一层来进行,代码显得很乱,不容易维护。

    顺便提一下,如果规定Funtion1执行完毕,才能执行Function2的话,那么我们就无需这么麻烦的设置回调了。直接利用下面代码:
    Function1();
    Function2();
    即可。但是这样出现一个问题,就是最后输出结果是一块儿输出的。也就是会在同一时刻输出"Function1执行完毕Function2执行完毕"。
    这是由于JS内部机制导致的,在JS内部,会将所有的更新UI操作排到最后进行,所以会导致同时输出。
    要解决这个问题很简单,只需要利用:
    Function1();
    setTimeout(Function2,100);即可

    二、Listeners(事件监听)


    事件监听是Jquery里面非常著名,也是采用的非常多的处理方式。比如说下面代码:
    $(".submit").on("click",function(){})
    就是通过监听按钮的点击事件来执行后续的操作。
    下面看代码模拟:

    <script type="text/javascript">
    
        var eventable = {
            on: function (event, cb) {
                $(this).on(event, cb);
            },
            trigger: function (event) {
                $(this).trigger(event);
            }
        }
    
        var TriggerDone = function (self) {
            self.trigger('done');
        }
    
        var Function3 = {
            run: function () {
                var self = this;
                setTimeout(function () {
                    $.ajax({
                        url: "GetTitle",
                        type: "post",
                        success: function (data) {
                            $(".container1").append(data.message);
                            TriggerDone(self);
                        }
                    });
                }, 500);
            }
        }
    
        var Function4 = {
            run: function () {
                var self = this;
                setTimeout(function () {
                    $(".container1").append("Function4执行完毕");
                    TriggerDone(self);
                },500);
            }
        }
    
        $.extend(Function3, eventable);
        $.extend(Function4, eventable);
    
        Function3.on('done', function (event) {
            Function4.run();
        });
    
        Function4.on('done', function () {
            $(".container1").append("任务完成。");
        });
        
        Function3.run();
    
    </script>
    <div class="container1" style="color:brown"></div>

    同样,我们得出了和第一种方式一样的结果,两个函数均为异步进行。

    三、PUB/SUB(发布订阅模式,也就是观察者模式)


    所谓的发布订阅模式就是指,源负责发布,然后一个或者多个目标进行接收订阅,一旦有新的信息,会主动推送给订阅者。
    下面我们采用Ben Alman的Tiny Pub/Sub插件来完成,这是一个Jquery插件,你可以在这里下载:https://github.com/cowboy/jquery-tiny-pubsub

    <script src="~/Content/ba-tiny-pubsub.min.js"></script>
    <script type="text/javascript">
        var Function5 = {
            run: function () {
                setTimeout(function () {
                    $.ajax({
                        url: "Home/GetResult",
                        type: "post",
                        success: function (data) {
                            $(".container2").append(data.message);
                            jQuery.publish("done");
                        }
                    });
                }, 500);
            }
        } 
    
        var Function6 = {
            run: function () {
                setTimeout(function () {
                    $(".container2").append("Function6执行完毕");
                }, 500);
            }
        }
        Function5.run(); 
    
        jQuery.subscribe("done", Function6.run); 
    
    </script>
    <div class="container2"></div>
    
    

    得到的最终结果是:AjaxFunction执行完毕.Function6执行完毕,这也完全符合我们的预期。

    四、Promises对象


    首先这个对象的介绍可以follow这个网站:http://wiki.commonjs.org/wiki/Promises/A  还有这个:http://www.html5rocks.com/zh/tutorials/es6/promises/
    其目的是为异步编程提供统一接口。
    每一个promise 对象都有一个then方法,可以指定回调函数。这样我们只需要以 func1().then(func2) 的形式进行调用即可。

    <script type="text/javascript">
        var Function7 = function () {
            var deferred = $.Deferred();
            alert(deferred.state());
            setTimeout(function () {
                $.ajax({
                    url: "Home/GetResult",
                    type: "post",
                    success: function (data) {
                        $(".container3").append(data.message);
                        if (deferred.state() === "pending") {
                            deferred.notify("正在处理中....");
                        }
                        deferred.resolve();  //可以带上参数进行传参操作。
                    }
                });
            }, 500);
            return deferred.promise();
        } 
    
        var Function8 = function () {
            var deferred = $.Deferred();
                setTimeout(function () {
                    $(".container3").append("Function8执行完毕");
                    deferred.resolve();
                }, 500);
                return deferred.promise();
        } 
    
        $.when(Function7()).then(Function8).then(function () {
            $(".container3").append("全部执行完毕");
        });
    </script>
    <div class="container3"></div>
    


    运行起来的时候,我们发现,事情是按照我们预想的方向发展。依次按顺序输出了: AjaxFunction执行完毕  Function8执行完毕  全部执行完毕。
    这样写的功能非常强大,当我们有很多的函数需要规定执行顺序的时候,我们可以利用这种方式进行链式执行。同时由于promise提供的强大的错误处理手段,不用担心整体的崩溃。

    粗略的写道这里,还希望你能够欣赏。有时间的话,准备专门详细研究下JQuery的Promise,敬请期待。

  • 相关阅读:
    本机可以,服务器却不行
    学习摘录1Hello, World!
    钻石问题
    OPEN OFFICE使用技巧
    操作符的重载
    函数重载
    关于“结构”好别扭的一段话
    多重继承
    OPEN OFFICE操作技巧3
    70个现代风格的HTML5 WordPress主题网站
  • 原文地址:https://www.cnblogs.com/scy251147/p/3761059.html
Copyright © 2011-2022 走看看