摘要:本篇教程介绍了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频道!
您输入的评论内容中包含违禁敏感词
我知道了
请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号