题目:红灯三秒亮一次,绿灯一秒亮一次,黄灯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. Git版本控制管理学习笔记4-文件管理和索引

        可以认为使用Git时,我们会遇到3个空间:工作目录.索引.版本库.我们关心的,就是在新建.修改等操作时,这三者之间发生了怎样的变化.     笼统的讲,就是在工作目录下编辑,在索引中积累修改, ...

  2. gdb的可视化工具安装

    红帽推出的insight https://www.sourceware.org/insight/index.php http://wiki.ubuntu.org.cn/Insight%E7%9A%84 ...

  3. eclipse的package, folder, source folder 异同以及相互转化

    1 相同点:都是文件夹; 不同点: 我们用面对对象思维来看; 首先说folder, 三者的父类(object),就是普通的文件夹,它和我们window下面使用的文件夹没有任何区别; source fo ...

  4. HRPlugin For Xcode发布(附源码地址)

    今天给大家介绍的这个插件,是我在IOS平台上开发以来,一些想法的集合体.因为本人时常感觉在开发过程中无论从GOOGLE资料查找和SQL数据库查询,正则表达式测试,SVN等,这些经常要做的操作中,耽误了 ...

  5. mybatis map常用数据类型

    JDBC Type Java Type CHAR String VARCHAR String LONGVARCHAR String NUMERIC java.math.BigDecimal DECIM ...

  6. html学习第三天—— 第12章——css布局模型

    清楚了CSS 盒模型的基本概念. 盒模型类型, 我们就可以深入探讨网页布局的基本模型了.布局模型与盒模型一样都是 CSS 最基本. 最核心的概念. 但布局模型是建立在盒模型基础之上,又不同于我们常说的 ...

  7. [NHibernate]利用LINQPad查看NHibernate生成SQL语句

    上篇文章中我们提到可以通过重写NHibernate的 EmptyInterceptor 拦截器来监控NHibernate发送给数据库的SQL脚本,今天看到有朋友用LINQPad工具来进行NHibern ...

  8. 我的Python学习之路 Python的初识与准备工作

    注:文笔不好,不喜勿喷,当个段子看看就好 一.初识Python 第一次听到Python是在2016年大概暑假 时候(即将大三),因为对黑客技术的蜜汁热爱(虽然自己并不会),在玄魂大大的公众微信号中看到 ...

  9. [转]ORACLE中Like与Instr模糊查询性能大比拼

    instr(title,'手册')>0  相当于  title like '%手册%' instr(title,'手册')=1  相当于  title like '手册%' instr(titl ...

  10. 一个快速排序(分类)及使用类似思想实现选择问题[c++实现]

    一.快速排序(快速分类)算法: 问题描述:给定线性集中n个元素和一个整数k,1<=k<=n,要求找出这n个元素中第k小的元素. 思想:选取数组A中的某个元素 t=A[s],然后将其他元素重 ...