Jason Axelrod Jason Axelrod - 3 months ago 12
jQuery Question

How do I turn setTimeouts to chainable plugins?

I have the following code:

showElem('.match');

setTimeout(function() {
showElem('.player');

setTimeout(function() {
showElem('.score');

}, inSpeed);
}, inSpeed);


This code calls the following function:

function showElem(elem) {
$(elem).removeClass('fast');
$(elem).addClass('display');
}


I would like to be replace the first piece of code with:

showElem('.match').delay(inSpeed).showElem('.player').delay(inSpeed).showElem('.score');


How would I accomplish this?

Answer

With the syntax you suggest it is not possible, because for that code would have to run synchronous, while setTimeout callbacks are asynchronous.

You could however do something similar with promises, using E6:

var inSpeed = 1000;

showElem('.match')
    .then( _ => delay(inSpeed))
    .then( _ => showElem('.player'))
    .then( _ => delay(inSpeed))
    .then( _ => showElem('.score'));

function delay(inSpeed) {
    return new Promise(function (resolve) {
        setTimeout(resolve, inSpeed);
    });
}

function showElem(elem) {
    return new Promise(function (resolve) {
        $(elem).removeClass('fast');
        $(elem).addClass('display');
        resolve();
    });
}
.fast { border: 2px solid red }
.display { background: yellow }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='match fast'>match</div>
<div class='player fast'>player</div>
<div class='score fast'>score</div>

non ES6 solution

This uses the jQuery Deferred method and bind:

var inSpeed = 1000;

showElem('.match')
    .then(delay.bind(null, inSpeed))
    .then(showElem.bind(null, '.player'))
    .then(delay.bind(null, inSpeed))
    .then(showElem.bind(null, '.score'));

function delay(inSpeed) {
    var prom = new $.Deferred();
    setTimeout(prom.resolve, inSpeed);
    return prom;
}

function showElem(elem) {
    var prom = new $.Deferred();
    $(elem).removeClass('fast');
    $(elem).addClass('display');
    prom.resolve();
    return prom;
}
.fast { border: 2px solid red }
.display { background: yellow }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='match fast'>match</div>
<div class='player fast'>player</div>
<div class='score fast'>score</div>

Comments