题目:红灯三秒亮一次,绿灯一秒亮一次,黄灯2秒亮一次;如何让三个灯不断交替重复亮灯?(用Promse实现)

三个亮灯函数已经存在:

function red(){
console.log('red');
}
function green(){
console.log('green');
}
function yellow(){
console.log('yellow');
}

这道题首先考察Promise的应用,Promise的详细说明请看我的这篇文章:闲话Promise机制。首先我们需要一个函数来实现时间控制:

var tic = function(timmer, cb){
return new Promise(function(resolve, reject) {
setTimeout(function() {
cb();
resolve();
}, timmer);
});
};

如果把问题简化一下,如果只需要一个周期,那么利用Promise应该这样写:

var d = new Promise(function(resolve, reject){resolve();});
var step = function(def) {
def.then(function(){
return tic(3000, red);
}).then(function(){
return tic(2000, green);
}).then(function(){
return tic(1000, yellow);
});
}

现在一个周期已经有了,剩下的问题是如何让他无限循环。说道循环很容易想到for while do-while这三个,比如:

var d = new Promise(function(resolve, reject){resolve();});
var step = function(def) {
while(true) {
def.then(function(){
return tic(3000, red);
}).then(function(){
return tic(2000, green);
}).then(function(){
return tic(1000, yellow);
});
}
}

如果你是这样想的,那么恭喜你成功踩了坑!这道题的第二个考查点就是setTimeout相关的异步队列会挂起知道主进程空闲。如果使用while无限循环,主进程永远不会空闲,setTimeout的函数永远不会执行!

正确的解决方法就是这道题的第三个考查点——递归!!!解决方案如下:

var d = new Promise(function(resolve, reject){resolve();});
var step = function(def) {
def.then(function(){
return tic(3000, red);
}).then(function(){
return tic(2000, green);
}).then(function(){
return tic(1000, yellow);
}).then(function(){
step(def);
});
}

整体代码如下:

function red(){
console.log('red');
}
function green(){
console.log('green');
}
function yellow(){
console.log('yellow');
} var tic = function(timmer, cb){
return new Promise(function(resolve, reject) {
setTimeout(function() {
cb();
resolve();
}, timmer);
});
}; var d = new Promise(function(resolve, reject){resolve();});
var step = function(def) {
def.then(function(){
return tic(3000, red);
}).then(function(){
return tic(2000, green);
}).then(function(){
return tic(1000, yellow);
}).then(function(){
step(def);
});
} step(d);

同时可以看到虽然Promise可以用来解决回调地狱问题,但是仍然不可避免的会有回调出现,更好的解决方案是利用Generator来减少回调:

var tic = function(timmer, str){
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log(str);
resolve(1);
}, timmer);
});
}; function *gen(){
yield tic(3000, 'red');
yield tic(1000, 'green');
yield tic(2000, 'yellow');
} var iterator = gen();
var step = function(gen, iterator){
var s = iterator.next();
if (s.done) {
step(gen, gen());
} else {
s.value.then(function() {
step(gen, iterator);
});
}
} step(gen, iterator);

最新文章

  1. Equals和ReferenceEquals
  2. java 读写properties
  3. Yii2 中自定义实例名称
  4. TestNG官方文档中文版(4)-运行TestNG
  5. [Leetcode] Recover Binary Search Tree
  6. android 修改系统的dialog样式
  7. HDU 2817 A sequence of numbers 整数快速幂
  8. <转载>无法解析的外部符号 _main,该符号在函数 ___tmainCRTStartup 中被引用
  9. J2SE知识点摘记(十三)
  10. javascript变量说明
  11. Chapter 2.策略模式
  12. JS中的函数和BOM
  13. jQuery点击下拉菜单的展示与隐藏
  14. nodejs--(一)http模板篇
  15. npm命令
  16. delphi idhttp post 普通提交乱码处理
  17. Jenkins 配置CI/CD任务
  18. 【3-30】document获取、事件、标记样式
  19. eclipse项目两个红点
  20. STM32 F4 GPIO Modes

热门文章

  1. [BI项目记]-新任务处理
  2. C#语言实现定时开启或禁用网卡小程序
  3. 安装.NET FRAMEWORK 4.5安装进度条回滚之后发生严重错误 代码0x80070643
  4. Win10 UI入门RelativePanel(2)
  5. CozyRSS开发记录15-获取和显示RSS内容
  6. obj转json
  7. IIR滤波器和FIR滤波器的区别与联系zz
  8. 关于这个博客以及C++入门该懂的一些东西
  9. WP8解析JSON格式(使用DataContractJsonSerializer类)(推荐)
  10. MyXls导出Excel的各种设置