zoukankan      html  css  js  c++  java
  • JS异步操作的几种模式(异步编程)

    1.回调函数方法:

      回调函数是异步操作最基本的方法

    function f1() {
      // ...
    }
    
    function f2() {
      // ...
    }
    
    f1();
    f2()
    

      两个函数f1f2,编程的意图是f2必须等到f1执行完成,才能执行。

      上面代码的问题在于,如果f1是异步操作,f2会立即执行,不会等到f1结束再执行。

      这时,可以考虑改写f1,把f2写成f1的回调函数。

    function f1(callback) {
      // ...
      callback();
    }
    
    function f2() {
      // ...
    }
    
    f1(f2);
    

      回调函数的优点是简单、容易理解和实现,缺点是不利于代码的阅读和维护,各个部分之间高度耦合(coupling),使得程序结构混乱、流程难以追踪(尤其是多个回调函数嵌套的情况),而且每个任务只能指定一个回调函数。

    2.事件监听方法:

      采用事件驱动模式。异步任务的执行不取决于代码的顺序,而取决于某个事件是否发生。

       还是以f1和f2为例。首先,为f1绑定一个事件(这里采用的jQuery写法) 

    f1.on('done', f2);
    function f1(){
    
        setTimeout(function () {
    
          // f1的任务代码
    
          f1.trigger('done');
    
        }, 1000);
    
      }

      f1.trigger('done')表示,执行完成后,立即触发done事件,从而开始执行f2。

      这种方法的优点是比较容易理解,可以绑定多个事件,每个事件可以指定多个回调函数,而且可以去耦合,有利于实现模块化。

      缺点是整个程序都要变成事件驱动型,运行流程会变得很不清晰。

    3.发布/订阅模式

      事件完全可以理解成“信号”,如果存在一个“信号中心”,某个任务执行完成,就向信号中心“发布”(publish)一个信号,其他任务可以向信号中心“订阅”(subscribe)这个信号,从而知道什么时候自己可以开始执行。这就叫做”发布/订阅模式”,又称“观察者模式”。 

    //首先,f2向"信号中心"jQuery订阅"done"信号
    jQuery.subscribe("done", f2);
    
    //f1写法
    function f1(){
    
        setTimeout(function () {
    
          // f1的任务代码
    
          jQuery.publish("done");
    
        }, 1000);
    
      }

      jQuery.publish("done")的意思是,f1执行完成后,向"信号中心"jQuery发布"done"信号,从而引发f2的执行。

      此外,f2完成执行后,也可以取消订阅(unsubscribe)

    jQuery.unsubscribe("done", f2);

    4.Promise对象  

      它的思想是,每一个异步任务返回一个Promise对象,该对象有一个then方法,允许指定回调函数。比如,f1的回调函数f2,可以写成:

    f1().then(f2);

      f1要进行如下改写(这里使用的是jQuery)

    function f1(){
        var dfd = $.Deferred();
        setTimeout(function () {
          // f1的任务代码
          dfd.resolve();
        }, 500);
        return dfd.promise;
      }

      优点在于,回调函数变成了链式写法,程序的流程可以看得很清楚,而且有一整套的配套方法,可以实现许多强大的功能。

      比如,指定多个回调函数:

     f1().then(f2).then(f3);

      再比如,指定发生错误时的回调函数:

    f1().then(f2).fail(f3);

      而且,它还有一个前面三种方法都没有的好处:如果一个任务已经完成,再添加回调函数,该回调函数会立即执行。所以,你不用担心是否错过了某个事件或信号。

  • 相关阅读:
    帝国 标签模板 使用程序代码 去除html标记 并 截取字符串
    iis6 伪静态 iis配置方法 【图解】
    您来自的链接不存在 帝国CMS
    帝国cms Warning: Cannot modify header information headers already sent by...错误【解决方法】
    .fr域名注册 51元注册.fr域名
    帝国网站管理系统 恢复栏目目录 建立目录不成功!请检查目录权限 Godaddy Windows 主机
    星外虚拟主机管理平台 开通数据库 出现Microsoft OLE DB Provider for SQL Server 错误 '8004' 从字符串向 datetime 转换失败
    ASP.NET 自定义控件学习研究
    CSS层叠样式表之CSS解析机制的优先级
    ASP.NET程序员工作面试网络收藏夹
  • 原文地址:https://www.cnblogs.com/yxkNotes/p/11738485.html
Copyright © 2011-2022 走看看