zoukankan      html  css  js  c++  java
  • 蛙蛙推荐:javascript异步任务流

    如下一些任务,每个任务都是异步执行的,因为它们都要去网络上取一些数据,而且不知道什么时间能执行完成。

    function output(msg){
    $(
    "#debug").append("<p>"+msg+"</p>");
    }
    function work1(callback){
    output(
    "begin work1");
    $.get(
    'data.js', function(data){
    output(
    "end work1");
    if(typeof callback == 'function'){
    callback();
    }
    });
    }
    function work2(callback){
    output(
    "begin work2");
    $.get(
    'data.js', function(data){
    output(
    "end work2");
    if(typeof callback == 'function'){
    callback();
    }
    });
    }
    function work3(callback){
    output(
    "begin work3");
    $.get(
    'data.js', function(data){
    output(
    "end work3");
    if(typeof callback == 'function'){
    callback();
    }
    });
    }

    如果我们同步调用这些任务,

    work1();
    work2();
    work3();

    会出现如下结果

    begin work1
    begin work2
    begin work3
    end work1
    end work2
    end work3

    但我们想第一个任务完成后再执行第二个任务,依次类推,如果不借助异步框架的支持,我们就需要修改work1,work2,work3的代码,让他们完成后执行相应的后续任务,这样以后要修改任务流就需要改动具体任务的代码,变化点比较分散。

    也可以在开始执行任务前准备一些回调函数,然后再开始,这样封装了变化点,提高了代码的可读性,大致如下

    var callback3 = function(){work3();};
    var callback2 = function(){work2(callback3);};
    var callback1 = function(){work1(callback2);}
    callback1();

    执行结果如下

    begin work1
    end work1
    begin work2
    end work2
    begin work3
    end work3

    可以看到这段代码虽然执行结果符合预期,但可读性和可维护性太差了,一大串匿名函数,而且写的顺序还得仔细注意,所以我写了个小框架了让它变的简单。

    function AsyncWorkManager(){
    this.works = [];
    }
    AsyncWorkManager.prototype.addWork
    = function(callee, caller){
    if(typeof callee!= 'function')
    throw {name:"TypeError",message:"work must be a function"};
    this.works.push([callee, caller]);
    };
    AsyncWorkManager.prototype.start
    = function(){
    var me = this;
    var arr = [];
    var j = 0;
    for(var i = this.works.length - 1;i >=0; i--){
    var fun = function(){
    var work = me.works[j++];
    work[
    0].call(work[1],arr.pop());
    };
    arr.push(fun);
    }
    arr.pop()();
    };

    代码很少,但效果很好,再次写调度代码就简单了,如下。

    var manager = new AsyncWorkManager();
    manager.addWork(work1);
    manager.addWork(work2);
    manager.addWork(work3);
    manager.start();

  • 相关阅读:
    Arch Linux中安装Anaconda
    Windows下使用Diskpart格式化U盘
    Jupyter Notebook的安装
    Docker的脚本安装
    pip无法正常使用卸载并重新安装
    Arch更新时failed to prepare transaction
    Privoxy将Socks代理转化HTTP代理
    Arch Linux下Visual Stdio Code在格式化C代码时报错
    GNOME 3.28 启用桌面图标
    Appium入门(8)__控件定位
  • 原文地址:https://www.cnblogs.com/onlytiancai/p/2074135.html
Copyright © 2011-2022 走看看