一道关于Promise应用的面试题

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

三个亮灯函数已经存在:异步

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应该这样写:code

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这三个,好比:htm

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的函数永远不会执行!blog

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

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);
相关文章
相关标签/搜索