Отложенная / обещаемая зависимость друг от друга

Я хотел бы реализовать вызовы зависимостей Deferred/Promise. Проблема в том, что я не понимаю, как сделать пошаговые вызовы для массива обработчиков, которые содержат асинхронные вызовы, например

У меня есть глобальный объект:

var options = {
    additionalHandler: []
    main : null
}

Затем добавьте основную функцию и обработчики, которые добавляют в сильную последовательность и также должны вызывать в этой последовательности

options.main = function(that, data){
    var that = this; //Todo: fix this should be button
    //Do some staff
}

var dialog = $(somedialog).dialog({
    autoOpen: false,
    modal: true,
    buttons: {
        "OK": function() {                            
            //There is the place where i have wait user answer to invoke innerDeferred.resolve(true) that is have to affected on global Deferred
            $(this).dialog("close");
        }
    },
    close: function () {
        //innerDeferred.resolve(false);
    }
});

options.additionalHandler.push(function(){
    dialog.dialog("open");
})

Затем, когда происходит нажатие кнопки, я запускаю / жду все обработчики и затем выполняю основную функцию, если все обработчики возвращают true

$("#someButton").on("click", function () {
    var self = this;
    if(typeof options !== "undefined"){
        var deferred = $.Deferred();
        if (options.additionalHandler &&  options.additionalHandler.length) // if we do not have(collect) any handlers we don't ran it all
        {
            $(options.additionalHandler).each(function () {
                if (typeof this !== "undefined" && typeof this === "function") {
                    deferred.then(this( /*??? deferred or innerDeferred */));
                }
            });
        }
        deferred.done(function (def) {
            if(def) // if all steps from all inner steps return true 
                options.main(self , someData));
        });               
    }
}

Это означает, что у меня есть один основной обработчик, который зависит от дополнительных ответов обработчика, которые возможно не существовали (если не существовало, мы просто переходим к основному обработчику), и вопрос заключается в том, как реализовать зависимость от результата асинхронного внутреннего отложенного вызова, который должен выполняться пошагово. шаг (в нашем случае диалоговое окно дождется ответа пользователя и перейдет в другое диалоговое окно или возможные вызовы ajax).

Update1:

Сверху вниз это псевдо реализация (код) и тоже не работает

Как это работает (обязательно):

user => add some itemp to backet
backet <= knows about some discount if user purchase 2 items and register new pop-up that says if you add 2 you'll have 50% sale.
user => add another item to backet 
backet <= this item will not available till next week, register another pop-up.
user = > push Order
Order => (pop-up) Discount if 2 do you (Yes-break /No -continue) => Item available on next week will wait ( Yes - continue/ No- break) => if (all.Continue) => push Order.

все работает как водопад, и я не вижу плюсов / минусов с отсрочкой / обещанием

2 ответа

Есть несколько проблем в коде.

Ваш deferred переменная все еще ссылается на оригинал Deferred который пуст, вам нужно обновить ваш deferred каждый раз, когда вы добавляете обратный вызов.

deferred = deferred.then(this( /*??? deferred or innerDeferred */));

Ваш чек на true внутри метода done вы должны убедиться, что все ваши обратные вызовы возвращаются true (по крайней мере, последний).

Если вы используете async обратные вызовы, убедитесь, что они возвращаются deffered случаи, которые возвращают истину.

Последнее, первый параметр, который вы передаете options.main не имеет значения, поскольку вы перезаписываете его внутри метода.

Вот решение с последовательной асинхронной операцией, реализуемой на обещаниях:

Получить отсюда

<!DOCTYPE html>
<html>
    <head>
        <script src="https://code.jquery.com/jquery-1.12.4.js" integrity="sha256-Qw82+bXyGq6MydymqBxNPYTaUXXq7c8v3CwiYwLLNXU=" crossorigin="anonymous"></script>
        <script src="https://code.jquery.com/ui/1.12.0/jquery-ui.js" integrity="sha256-0YPKAwZP7Mp3ALMRVB2i8GXeEndvCq3eSl/WsAl1Ryk=" crossorigin="anonymous"></script>
        <link rel="stylesheet" href="https://code.jquery.com/ui/1.12.0/themes/smoothness/jquery-ui.css" crossorigin="anonymous">

        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">        <!-- Latest compiled and minified JavaScript -->
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>

        <script>
            $(function() {
                var options = {
                    additionalHandler: [],
                    main : null
                }                

                options.main = function(confirmed){                    
                    $("#result").html("Confirmed: " + confirmed);
                };

                options.additionalHandler.push(function(resolve, reject, data){
                    var dialog1 = $("#dialog1").dialog({
                        autoOpen: false,
                        modal: true,
                        buttons: {
                            "OK": function() {                            
                                resolve(true);
                                $(this).dialog("close");
                            }
                        },
                        close: function () {
                            resolve(false);
                        }
                    });
                    dialog1.dialog("open");
                });

                options.additionalHandler.push(function(resolve, reject, data){
                    var dialog2 = $("#dialog2").dialog({
                        autoOpen: false,
                        modal: true,
                        buttons: {
                            "OK": function() {                            
                                resolve(true);
                                $(this).dialog("close");
                            }
                        },
                        close: function () {
                            resolve(false);
                        }
                    });
                    dialog2.dialog("open");
                });

                Array.prototype.chainExecute = function(data){
                    var array = this;
                    var results = [];
                    return array.reduce(function(previous, current) {
                        return previous.then(function(result) {
                            return new Promise(function(resolve, reject) {
                                current(resolve, reject, data); 
                            }).then(function(result) {
                                results.push(result);
                                return results;
                            });
                        });
                    }, Promise.resolve());
                };

                $("#orderPush").on("click", function () {
                    var self = this;
                    if(typeof options !== "undefined")
                    {
                        options.additionalHandler.chainExecute("Blah").then(function(result) {
                            options.main(result);
                        }, function(reason) {
                            options.main(reason);
                        })                                        
                    }
                });
            });        
        </script>
    </head>
    <body>
        <div id="dialog1" style="display: none">
                <div>Discount if 2 items!</div>
        </div>
        <div id="dialog2" style="display: none">
                <div>Been available on next week!</div>
        </div>

        <button type="button" class="btn btn-primary" id="orderPush">Process order</button>
        <p><strong id="result"></strong></p>
    </body>
</html>

Другие вопросы по тегам