zoukankan      html  css  js  c++  java
  • 处理异步的几种方法

    Javascript语言的执行环境是"单线程"(single thread),就是指一次只能完成一件任务。

    处理异步的几种方法:

    1、回调函数:回调是一个函数被作为一个参数传递到另一个函数里,在那个函数执行完后再执行。

    假设: f1、f2两个函数,后者等待前者的执行完成后再执行。如果f1是一个很耗时的任务,可以考虑改写f1,把f2写成f1的回调函数。

    function f1(callback){

      setTimeout(function () {
        // f1的任务代码
        callback();
      }, 1000);
    }
    // 执行
    f1(f2);

    通过回调,实现了f2函数在f1之后执行;注意:回调并不一定就是异步;

    2、时间监听:采用事件驱动模式。任务的执行不取决代码的顺序,而取决于某一个事件是否发生。监听函数有:on,bind,listen,addEventListener,observe;

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

    f1.on('done',f2);

    上面代码意思是,当f1发生done事件,就执行f2。

    然后对f1进行改写:

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

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

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

    这种方法的缺点:整个程序都要变成事件驱动型,运行流程会变得不清晰。

    三、发布/订阅

    我们假定,存在一个"信号中心",某个任务执行完成,就向信号中心"发布"(publish)一个信号,其他任务可以向信号中心"订阅"(subscribe)这个信号,从而知道什么时候自己可以开始执行。这就叫做"发布/订阅模式"(publish-subscribe pattern),又称"观察者模式"(observer pattern)。

    这个模式有多种实现,下面采用的是Ben Alman的Tiny Pub/Sub,这是jQuery的一个插件。

    首先,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);

    这种方法的性质与"事件监听"类似,但是明显优于后者。因为我们可以通过查看"消息中心",了解存在多少信号、每个信号有多少订阅者,从而监控程序的运行。

    四、promise对象(promise 模式)

    (1)promise对象是commonJS工作组提出的一种规范,一种模式,目的是为了异步编程提供统一接口。

    (2)promise是一种模式,promise可以帮忙管理异步方式返回的代码。他讲代码进行封装并添加一个类似于事件处理的管理层。我们可以使用promise来注册代码,这些代码会在在promise成功或者失败后运行。

    (3)promise完成之后,对应的代码也会执行。我们可以注册任意数量的函数再成功或者失败后运行,也可以在任何时候注册事件处理程序。

    (4)promise有两种状态:1、等待(pending);2、完成(settled)。

    promise会一直处于等待状态,直到它所包装的异步调用返回/超时/结束。

    (5)这时候promise状态变成完成。完成状态分成两类:1、解决(resolved);2、拒绝(rejected)。

    (6)promise解决(resolved):意味着顺利结束。promise拒绝(rejected)意味着没有顺利结束。

    复制代码
    //promise
    var p=new Promise(function(resolved))
    //在这里进行处理。也许可以使用ajax
    setTimeout(function(){
       var result=10*5;
       if(result===50){
          resolve(50);
       }else{
         reject(new Error('Bad Math'));
      }
    },1000);
    });
    p.then(function(result){
        console.log('Resolve with a values of %d',result);
    });
    p.catch(function(){
       console.error('Something went wrong');
    });
    复制代码

    (1)代码的 关键在于setTimeout()的调用。

    (2)重要的是,他调用了函数resolve()和reject()。resolve()函数告诉promise用户promise已解决;reject()函数告诉promise用户promise未能顺利完成。

    (3)另外还有一些使用了promise代码。注意then和catch用法,可以将他们想象成onsucess和onfailure事件的处理程序。

    (4)巧妙地方是,我们将promise处理与状态分离。也就是说,我们可以调用p.then(或者p.catch)多少次都可以,不管promise是什么状态。

    (5)promise是ECMAscript 6管理异步代码的标准方式,javascript库使用promise管理ajax,动画,和其他典型的异步交互。

    简单的说,它的思想是:每一个异步任务返回一个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);

    而且,它有一个前面三种方法都没有的好处:如果一个任务已经完成,再添加回调函数,该回调函数会立即执行。

    所以你不用担心错过某一个事件或者信号。

    这种方法的缺点:编写和理解都相对比较难。

    五、优雅的async/await

    参考链接:

    http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF%BC%BFjavascript.html

    https://www.cnblogs.com/chengxs/p/6497575.html

    http://mp.weixin.qq.com/s?__biz=MzAwNTAzMjcxNg==&mid=2651425195&idx=1&sn=eed6bea35323c75f0c43ae61818c0a55&chksm=80dff7c8b7a87edeb834cc4aabf0eec40c7566b45abd5c58b56625dc0efd77d15c9e64534140&mpshare=1&scene=1&srcid=02260hYIB6d5lSLVwyvPIUWX#rd

    https://segmentfault.com/a/1190000008489550

  • 相关阅读:
    反转链表 16
    CodeForces 701A Cards
    hdu 1087 Super Jumping! Jumping! Jumping!(动态规划)
    hdu 1241 Oil Deposits(水一发,自我的DFS)
    CodeForces 703B(容斥定理)
    poj 1067 取石子游戏(威佐夫博奕(Wythoff Game))
    ACM 马拦过河卒(动态规划)
    hdu 1005 Number Sequence
    51nod 1170 1770 数数字(数学技巧)
    hdu 2160 母猪的故事(睡前随机水一发)(斐波那契数列)
  • 原文地址:https://www.cnblogs.com/jaywu/p/12582628.html
Copyright © 2011-2022 走看看