zoukankan      html  css  js  c++  java
  • LazyMay:实现同步和异步任务的顺序执行

    在掘金看到的文章,流程控制同步和异步任务的顺序执行,收益匪浅,工作中能用到。

    1、实现以下效果

    实现一个LazyMan,可以按照以下方式调用:
    LazyMan(“Hank”)输出:
    Hi! This is Hank!
    
    LazyMan(“Hank”).sleep(10).eat(“dinner”)输出
    Hi! This is Hank!
    //等待10秒..
    Wake up after 10
    Eat dinner~
    
    LazyMan(“Hank”).eat(“dinner”).eat(“supper”)输出
    Hi This is Hank!
    Eat dinner~
    Eat supper~
    
    LazyMan(“Hank”).sleepFirst(5).eat(“supper”)输出
    //等待5秒
    Wake up after 5
    Hi This is Hank!
    Eat supper
    
    以此类推。

    这是典型的JavaScript流程控制,问题的关键是如何实现任务的顺序执行。在Express有一个类似的东西叫中间件,这个中间件和我们这里的吃饭、睡觉等任务很类似,每一个中间件执行完成后会调用next()函数,这个函数用来调用下一个中间件。

    对于这个问题,我们也可以利用相似的思路来解决,首先创建一个任务队列,然后利用next()函数来控制任务的顺序执行:

    1.2 队列方式实现

    function _LazyMan(name){
      this.tasks=[];
      var self=this;
      var fn=(function(n){
        var name=n;
        return function(){
          console.log("Hi! this is "+name+"!");
          self.next();
        }
      })(name);
      this.tasks.push(fn);
      setTimeout(function(){
        self.next();
      },0);  // 在下一个事件循环启动任务
    }
    /* 事件调度函数 */
    _LazyMan.prototype.next=function(){
      var fn=this.tasks.shift();
      fn && fn();
    }
    _LazyMan.prototype.eat=function(name){
      var self=this;
      var fn=(function(name){
        return function(){
          console.log("Eat "+name+" ~");
          self.next()
        }
      })(name);
      this.tasks.push(fn);
      return this; // 实现链式调用
    }
    _LazyMan.prototype.sleep=function(time){
      var self=this;
      var fn=(function(time){
        return function(){
          setTimeout(function(){
            console.log("Wake up after "+time+" s!");
            self.next();
          },time*1000);
        }
      })(time);
      this.tasks.push(fn);
      return this;
    }
    _LazyMan.prototype.sleepFirst=function(time){
      var self=this;
      var fn=(function(time){
        return function(){
          setTimeout(function(){
            console.log("Wake up after "+time+" s!");
          },time*1000);
        }
      })(time);
      this.tasks.unshift(fn);
      return this;
    }
    /* 封装 */
    function LazyMan(name){
      return new _LazyMan(name);
    }

     

    1.3 promise方式实现

    lazyman里边含有链式调用,那么每一个子任务 return this;这个程序支持任务优先顺序,那么就需要两个贯穿全场的Promise对象:第一,普通顺序promise;第二,插入顺序promise,同时插入顺序是阻塞普通顺序的,代码如下:
    function _LazyMan(name){
      this.orderPromise=this.newPromise(); // 定义顺序promise对象
      this.insertPromise=this.newPromise(); // 定义插入promise对象
      this.order(function(resolve){
        console.log(name);
        resolve();
      })
    }
    
    _LazyMan.prototype={
      /*实例化promise对象工厂*/
      newPromise:function(){
        return new Promise(function(resolve,reject){
          resolve();
        })
      },
      order:function(fn){
        var self=this;
        this.orderPromise=this.orderPromise.then(function(){
          return new Promise(function(resolve,reject){
            //如果有insertPromise,阻塞orderPromise.
            self.fir?self.insertPromise.then(function(){
              fn(resolve)
            }):fn(resolve)
          })
        })
      },
      insert:function(fn){
        var self=this;
        this.fir=true;
        this.insertPromise=this.insertPromise.then(function(){
          return new Promise(function(resolve,reject){
            fn(resolve);
            self.fir=false;
          })
        })
      },
      sleepFirst:function(time){
        this.insert(function(resolve){
          setTimeout(function(){
            console.log('wait '+time+' s,other logic');
            resolve();
          },time*1000)
        })
        return this;
      },
      eat:function(something){
        this.order(function(resolve){
          console.log(something+' ~~');
          resolve();
        })
        return this;
      },
      sleep:function(time){
        this.order(function(resolve){
          setTimeout(function(){
            console.log('sleep '+time+' s');
          },time*1000);
        })
        return this;
      }
    }
    
    //接口封装。
    function LazyMan(name) {
        return new _LazyMan(name);
    }
    //调用测试
    LazyMan(‘RoryWu‘).firstTime(1).sleep(2).firstTime(3).eat(‘dinner‘).eat(‘breakfast‘);
    // 弹出:
    // wait 1 s, other logic
    // wait 3 s, other logic
    // RoryWu
    // sleep 2 s
    // dinner~~
    // breakfast~~

    原文地址:https://juejin.im/post/59c0da1f5188252c24747715

  • 相关阅读:
    echo 变量不加引号出错
    linux以16进制方式查看文件
    批量删除符合条件的文件
    sed删除行
    linux用户环境变量
    脚本路径问题_dirname
    shell脚本返回字符串
    关于Unix时间戳
    grunt用来压缩前端脚本
    JAVA ThreadPoolExecutor(转)
  • 原文地址:https://www.cnblogs.com/lvmylife/p/8493144.html
Copyright © 2011-2022 走看看