promise應用示例講解

Q:紅燈三秒亮一次,綠燈一秒亮一次,黃燈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);

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章