延迟/承诺相互依赖

时间:2018-04-19 16:03:03

标签: javascript jquery jquery-ui promise deferred

我想实现Deferred / Promise的依赖调用。问题是我不知道如何逐步调用包含异步调用的处理程序数组,例如。

我有全局对象:

select col1, col2, col3, col4
from (select t.*,
             sum(case when col4 = 'XXX' then 1 else 0 end) over (partition by col1, col)
      from t
     ) t
where col4 is null or cnt = 1;

然后添加主要功能和处理程序,这些功能和处理程序添加强顺序,并且还需要调用此序列

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

当按钮点击发生时,我运行/等待所有处理程序然后执行main函数,如果所有处理程序都返回true

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");
})

这意味着我有一个主处理程序依赖于可能不存在的其他处理程序答案(如果不存在我们只是去主处理程序),问题是如何实现依赖于异步内部延迟调用结果应该运行步骤-by-step(对话框在我们的例子中等待用户回答并转到另一个对话框或可能的ajax调用)。

UPDATE1:

从上到下这是伪实现(代码),也不起作用

这是如何工作的(必需):

$("#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));
        });               
    }
}

一切都像瀑布一样,我没有看到延迟/承诺的利弊

2 个答案:

答案 0 :(得分:1)

代码中存在几个问题。

您的deferred变量仍然指的是原始Deferred为空,您需要在每次添加回调时更新deferred

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

检查完成方法中的true,您需要确保所有回调都返回true(至少是最后一个)。

如果您使用async回调,请确保它们返回返回true的deffered个实例。

最后一件事,你传递给options.main的第一个参数并不重要,因为你在方法中覆盖了它。

答案 1 :(得分:0)

这是在promises上使用序列异步操作实现的解决方案:

here获取



<!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>
&#13;
&#13;
&#13;