题目:红灯三秒亮一次,绿灯一秒亮一次,黄灯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. react native RadioButton(单选按钮)

    刚刚写完这个多选按钮,我觉得没有单选的话,总会觉得有一点点不爽,因为在项目中我也没有用到单选,所以我没有好好研究源码,所以我在Github上找了一下,发现有一个挺好的,简单,不花哨. 在Github上 ...

  2. 【转】http头部详解

    原地址:http://www.cnblogs.com/ziwuge/archive/2011/09/27/2193385.html HTTP 头部解释 1. Accept:告诉WEB服务器自己接受什么 ...

  3. Effective C++ 笔记1

    条款1:视C++为一个语言联邦 1.C.Object-Oriented C++.Template C++ .STL 组成了C++,高效编程取决你使用C++的哪一部分 条款2:尽量用const ,enu ...

  4. Java_新浪微博SDK_jar包下载

    新浪微博开放平台API_jar包下载地址:jar包(猛戳) --by HsuChan

  5. iOS UIColor RGB HEX

    +(UIColor *)colorWithR:(CGFloat)r g:(CGFloat)g b:(CGFloat)b a:(CGFloat)a{ return [UIColor colorWithR ...

  6. git本地有修改如何强制更新

    本地有修改和提交,如何强制用远程的库更新更新.我尝试过用git pull -f,总是提示 You have not concluded your merge. (MERGE_HEAD exists). ...

  7. Linux Shell 流程控制语句

    * 本文主要介绍一些Linux Shell 常用的流程控制语句* 1. if 条件语句:if-then/if-elif-fi/if- else-fi if [条件判断逻辑1];then command ...

  8. Thread与Runnable的一个小陷阱

    Java里面运行一个线程可以通过继承Thread的方式,也可以通过实现Runnable的接口来实现,那么两者能不能混用呢,比如以下的例子: public class JavaTest extends ...

  9. RStudio技巧02_Extract Function

    RStudio 可以在 source 编辑器中分析一组选择的代码,并自动将其转化成再次使用的函数.任何选择中的"free"变量( 选择引用对象但不创建)将转化为函数参数. (也可使 ...

  10. 使用mongodump将mongodb数据备份带JOSN文件

    备份: 首先,mongodb要连接到指定数据库 在指定数据库目录下,shift+右键--在此次打开命令行--输入以下命令: mongodump -d databaseName -o backup 备份 ...