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

  • 相关阅读:
    android 75 新闻列表页面
    android 74 下载文本
    android 73 下载图片
    android 72 确定取消对话框,单选对话框,多选对话框
    android 71 ArrayAdapter和SimpleAdapter
    android 70 使用ListView把数据显示至屏幕
    maven如何将本地jar安装到本地仓库
    Centos6.7搭建ISCSI存储服务器
    解决maven打包编译出现File encoding has not been set问题
    MySQL 解决 emoji表情 的方法,使用utf8mb4 字符集(4字节 UTF-8 Unicode 编码)
  • 原文地址:https://www.cnblogs.com/lvmylife/p/8493144.html
Copyright © 2011-2022 走看看