JavaScript基础教程 Promise实现的lazyman
沉沙 2018-09-20 来源 : 阅读 627 评论 0

摘要:本篇教程介绍了JavaScript基础教程 Promise实现的lazyman,希望阅读本篇文章以后大家有所收获,帮助大家对JavaScript的理解更加深入。

本篇教程介绍了JavaScript基础教程 Promise实现的lazyman,希望阅读本篇文章以后大家有所收获,帮助大家对JavaScript的理解更加深入。

<


  首先请看通过setTimeout实现的:

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!");
                self.next();
            }, time * 1000);
        }
    })(time);
    this.tasks.unshift(fn);
    return this;
}
/* 封装 */
function LazyMan(name){
    return new _LazyMan(name);
}
LazyMan('Hank').sleepFirst(5).sleep(10).eat('dinner')

分析:
  用setTimeout模拟线程,有一个事件处理队列(this.tasks),然后每一个事件内部会调用事件调度函数(next),每一次的业务逻辑是通过定义的闭包函数fn,fn内部在处理完自身业务会执行next函数。
于是就想起处理这种含有异步并且有一定阻塞的业务,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;
            })
        })
    },
    firstTime: 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');
                resolve()
            },
            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~~

 
注意每一个任务的业务逻辑都是通过回调函数的形式实现的,内部拥有两种API:
  1 this.order(function(){ ... })
  2 this.insert(function() {... })
这里的核心需要注意以下几点:
  1 每一次任务的业务逻辑函数,就是这个回调函数传给对应的API,执行场地在它那。
  2 每一个API的执行权利交给任务函数自身,是通过参数传递的方式,例如: fn(resolve),每一个任务函数在执行完自身业务逻辑后,通过resolve()改变Promise对象状态为Resolved(其他:rejected pending).
  3 连个API的优先级实现,通过一个this.fir的状态值来判断是否含有插入promise对象,如果有就,就做一件事情改变fn发生的时间: insertPromise.then(function(){ fn(resolve) })
 
通过上边的实现,最后总结一下,在设计程序的时候,首先想想程序的大概构成,然后在开始写,这样大思路不会跑,进而很快就写出来了。

   

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标WEB前端JavaScript频道!

本文由 @沉沙 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程