题目:红灯三秒亮一次,绿灯一秒亮一次,黄灯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);

一道关于Promise应用的面试题的更多相关文章

  1. 一道非常棘手的 Java 面试题:i++ 是线程安全的吗

    转载自  一道非常棘手的 Java 面试题:i++ 是线程安全的吗 i++ 是线程安全的吗? 相信很多中高级的 Java 面试者都遇到过这个问题,很多对这个不是很清楚的肯定是一脸蒙逼.内心肯定还在质疑 ...

  2. 关于一道简单的Java 基础面试题的剖析: short s1=1;s1 = s1 +1会报错吗?

    package common; public class ShortTypeTest { /* * @param args */ public static void main(String[] ar ...

  3. 从一道没人能答对的面试题聊聊Java的值传递

    这是一道我们公司的面试题,从招第二个Java以来就一直存在了.但是面试了这么长的时间还没有一个人可以全部答对,让我们一度以为是这题出的不对.首先请看面试题. 以下运算的输出分别是多少: ```java ...

  4. 集合中存的是引用,分析一道容易混淆的Java面试题

    我们自定义的类是以引用的形式放入集合,如果使用不当,会引发非常隐蔽的错误.就拿我经常问到的一个面试题来说明这个知识点. 第一步,我们定义一个Car类型的类,其中只有一个int类型id属性. 第二步,创 ...

  5. 一道关于js正则表达式的面试题

    这道面试题明显是要用到正则表达式来解决的,由于太久没有写正则表达式了,一时之间竟然写不出来,所以记录一下笔记,下面直接上代码: function parseUrl(str) { // 判断是否传入参数 ...

  6. OpenJDK源码研究笔记(二)-Comparable和Comparator2个接口的作用和区别(一道经典的Java笔试面试题)

    Comparable和Comparator是JDK中定义的2个比较接口,很相似,但又有所不同. 这2个接口的作用和区别也是Java中的常见经典面试题. 下面我们就来详细介绍下这2个接口的定义.作用.区 ...

  7. 一道简单的for循环面试题(数字龙形排序)

    本道题是我从网上见到的,因为是一道很久没做的循环题,自己的思路也是陷入了一些思维陷阱中,后来经过把大脑放空,重新看这道题后,思路立马就出来了. 题目就是完成如下图所示的效果: 我一开始是想着将它按照奇 ...

  8. 一道简单到爆 Java面试题,居然挂了一票人

    很多时候bug往往都是出在,我们觉得非常简单,不起眼的基础知识上 年前公司最后一波招人,为年后项目做技术储备,主要招聘对象初中级Java开发,要求也并没有多苛刻,唯一一点基础稍好,快速上手做项目就行. ...

  9. 一道值得思考的fork()面试题

    程序如下,判断输出多少个'_' ./a.out int main(){ ; i < ; ++i){ fork(); printf("_"); } } 熟悉fork的话,这里很 ...

随机推荐

  1. F#之旅8 - 图片处理应用之动画二维码

    首先,先介绍下什么是动画二维码.前些天在网上闲逛,突然看到一个开源项目,发现一种二维码的新玩法.https://github.com/sylnsfar/qrcode/blob/master/READM ...

  2. TP5.0源生Excel导出

    PHPExcel类在TP5里边并不能很好的兼容,使用起来很麻烦. 不像是tp3.2那样直接import()加进来就能new,因为它里边的命名空间找不到.总是说undefined class. 如果是使 ...

  3. poj3311 TSP经典状压dp(Traveling Saleman Problem)

    题目链接:http://poj.org/problem?id=3311 题意:一个人到一些地方送披萨,要求找到一条路径能够遍历每一个城市后返回出发点,并且路径距离最短.最后输出最短距离即可.注意:每一 ...

  4. python 小程序 比较目录间的差异

    比较目录间的差异: I 只按照名称做了比较,如果目录的文件名称相同,但是内容不同脚本认为为相同文件 II 针对目录下面的目录没有循环比较,只是比较了目录的名称 import sys, os def d ...

  5. 四则运算app代码上传GITHUB

    团队: 郭志豪:http://www.cnblogs.com/gzh13692021053/ 杨子健:http://www.cnblogs.com/yzj666/ 刘森松:http://www.cnb ...

  6. C# 文件读写

    1.文本文件读写 //读 FileStream fs = new FileStream(filepath, FileMode.Open, FileAccess.Read); StreamReader ...

  7. Mac AppleScript 自动完成按键

    本人用AppleScript成功实现了打开锐捷app,并且在用户验证框输入我的用户密码,然后强制退出锐捷.(至于为什么这么做呢?用校园网的痛苦,一言难尽啊!) 学习以下内容,首先你要自行百度资料来学习 ...

  8. 关于null值的排序

    关于空值null的排序问题   Oracle排序中NULL值处理的五种常用方法: 1.缺省Oracle在Order by 时缺省认为null是最大值,所以如果是ASC升序则排在最后,DESC降序则排在 ...

  9. IIR滤波器和FIR滤波器的区别与联系zz

      -------------------------------------------------------------------------------------------------- ...

  10. VS2015 RTM与ASP.NET 5 RC1之坑

    最近Asp.Net 5的RC1出来了 VS2015的Update1也开始进入RC阶段 嗯,微软尿性,是时候转移到VS2015了 开始踩坑之旅 装好VS2015后,当然是开始折腾ASP.Net 5嘛 建 ...