JSFiddle - React, Tailwind, and code Playground

HTML

<div id="div1"></div>
<div id="div2"></div>
<div id="div3"></div>
<div id="info"></div>

CSS

div {
    width: 40px;
    height: 40px; 
    position: absolute;
}

#div1 {
    background-color: red;
}
#div2 {
    background-color: green;
    left: 45px;
}
#div3 {
    background-color: blue;
    left: 90px;
}

#info {
    position: absolute;
    bottom: 0;
    width: 100%;
    height: 50%;
}

JavaScript

(function() {
    wait = function(first) {
        return new wait.Init(first);
    }

    wait.Init = function(first) {
        first.call(this, this.callback);
    }

    wait.Init.prototype = {
        deferred: [],
        callback: function() {
            this.args = [].slice.call(arguments);
            this.args.unshift(this.callback);
            if (this.deferred.length) {
                this.done = false;
                this.deferred[0].apply(this, this.args);
                this.deferred.shift();
            }
            if (!this.deferred.length) {
                this.done = true;
            }

        },
        wait: function(run) {

            if (this.done) {
                console.log(this.args)
                run.apply(this, this.args);
                self.done = false;
            } else {
                this.deferred.push(run);
            }
            return this;
        }
    }




    var log = function(text) {
        $('#info').prepend(text + '<br>');
    }

    /* Пример */
    w = wait(function(runNext) {
        log('Первая анимация пошла');

        $('#div1').animate({
            top: 30
        }, 1000, function() {
            runNext(1, 2); //передаем какие-нибудь аргументы в следующий вызов
        });

    }).wait(function(runNext, a, b) {
        log('Вторая анимация пошла, a=' + a + ' b=' + b); //используем аргументы из предыдущего вызова

        $('#div2').animate({
            top: 50
        }, 1000, runNext);

    }).wait(function(runNext) {
        log('Ждем две секунды');

        setTimeout(function() {
            log('Две секунды прошли');
            log('Выполнена последняя функция из цепочки');
            runNext(1, 3);
        }, 1000);

    })

    setTimeout(function() {
        log('Большая задержка завершилась');
        w.wait(function(runNext, a, b) {
            log('Третья анимация пошла, a=' + a + ' b=' + b);

            $('#div3').animate({
                left: 50
            }, 1000,...