• 异步JS


    最近忙于工作项目,很久没有写博客了,然而博客还是得写,帮助很大。三言两语也好,以后尽量抽空多写写。欢迎指正交流。

    第一次接触到异步的概念来自于ajax,即页面向服务端发请求,不等待返回结果而继续向后执行,当结果返回时执行回调,回调函数执行的时机是不确定的,取决于服务端何时返回结果。相对的,同步就是指一直等到结果返回后才继续向后执行。

    我理解中,JS中实现异步的方式有两种:回调事件监听


    一. 回调(callback)

    最基本的回调方式,用一个简单的应用场景来阐述,假设我们要搜索数据,然后进行处理,最后显示结果,用异步来实现。在现实工作中这些函数会发出ajax请求并得到返回结果,现在我们就用setTimeout来简单模拟一下

     1 function finder(records, callback) {
     2     setTimeout(function() {
     3         records.push(3, 4);
     4         callback(records);
     5     }, 1000);
     6 }    
     7 
     8 function processer(records, callback) {
     9     setTimeout(function() {
    10         records.push(5, 6);
    11         callback(records);
    12     }, 1000);
    13 }
    1 finder([1, 2], function(records) {
    2     processor(records, function(records) {
    3         console.log(records);
    4     });
    5 });

    我们调用finder函数,传入了一个回调函数,在这个回调函数中我们又调用processor函数,给它传入另一个回调函数。起个名字来引用回调函数可以使代码更易读

    1 function onFinderDone(records) {
    2     processor(records, onProcessorDone);
    3 }
    4 
    5 function onProcessorDone(records) {
    6     console.log(records);
    7 }
    8 
    9 finder([1, 2], onFinderDone);

    这种方式简单好理解,但其最大的一个缺点是你只能传入一个回调函数。

    二. 事件监听(listener)

    这块用到了jQuery的一些方法,不必太在意,重点在于阐述道理

    首先我们需要两个对象,一个负责搜索数据,一个负责处理数据

     1 var finder = {
     2     run: function(records) {
     3         var self = this;
     4         setTimeout(function() {
     5             records.push(3, 4);
     6             self.trigger('done', [records]);
     7         }, 1000);
     8     }
     9 };
    10 
    11 var processor = {
    12     run: function(records) {
    13         var self = this;
    14         setTimeout(function() {
    15             records.push(5, 6);
    16             self.trigger('done', [records]);
    17         }, 1000);
    18     }
    19 };

    与上例回调方式对比,我们把调用回调函数替换成了trigger方法,定义如下

    1 var eventable = {
    2     on: function(event, callback) {
    3         $(this).on(event, callback);
    4     },
    5     
    6     trigger: function(event, args) {
    7         $(this).trigger(event, args);
    8     }
    9 };

    让我们的finder和processor对象获得事件监听、发布的能力

    1 $.extend(finder, eventable);
    2 $.extend(processor, eventable);

    执行

    1 finder.on('done', function(event, records) {
    2     processor.run(records);
    3 };
    4 
    5 processor.on('done', function(event, records) {
    6     console.log(records);
    7 };
    8 
    9 finder.run([1, 2]);

    这种模式最大的优点在于你可以指定任意多个事件处理函数

    原文中这一块过于依赖jQuery库,这里我参考了martinfowler的事件聚合(Event Aggregator),(原文http://martinfowler.com/eaaDev/EventAggregator.html或参考汤姆大叔的深入理解javascript系列),有兴趣的同学可以看看

     1 function Event(name) {
     2     var handlers = [];
     3     this.getName = function() {
     4         return name;
     5     };
     6     this.addHandler = function(handler) {
     7         handlers.push(handler);
     8     };
     9     this.removeHandler = function(handler) {
    10         for (var i = 0; i < handlers.length; i++ ) {
    11             if (handlers[i] == handler) {
    12                 handlers.splice(i , 1);
    13                 break;
    14             }
    15         }
    16     };
    17     this.fire = function(eventArgs) {
    18         for (var i = 0; i < handlers.length; i++ ) {
    19             handlers[i](eventArgs);
    20         }
    21     };
    22 }
    23 
    24 function EventAggregator() {
    25     var events = [];
    26     function getEvent(eventName) {
    27         return $.grep(events, function(event) {
    28             return event.getName() == eventName;
    29         })[0];
    30     }
    31     this.subscribe = function(eventName, handler) {
    32         var event = getEvent(eventName);
    33         if (!event) {
    34             event = new Event(eventName);
    35             events.push(event);
    36         }
    37         event.addHandler(handler);
    38     };
    39     this.publish = function(eventName, eventArgs) {
    40         var event = getEvent(eventName);
    41         if(!event) {
    42             event = new Event(eventName);
    43             events.push(event);
    44         }
    45         event.fire(eventArgs);
    46     };
    47 }

     译自:http://sporto.github.io/blog/2012/12/09/callbacks-listeners-promises/

  • 相关阅读:
    敏捷开发设计模式的五大原则(读敏捷软件开发:原则、模式与实践笔记记录一下)
    使用AOP和Semaphore对项目中具体的某一个接口进行限流
    java正则使用全记录!
    推荐一本书学习springcloud书籍的SpringCloud微服务全栈技术与案例解析
    使用springboot Admin 2.0.6版本 集成监控springcloud微服务应用
    推荐一本学习Groovy的书籍Groovy程序设计!
    Datagrip 快捷键和常用插件持续更新一集一些使用技巧
    Eclipse中项目不会自动编译问题的坑和注意点
    使用Groovy的mixin方法注入,和mixedIn属性实现过滤链
    vscode常用快捷键和插件(持续更新),以及一些常用设置的坑和技巧
  • 原文地址:https://www.cnblogs.com/coiorz/p/4678515.html
Copyright © 2020-2023  润新知