如何在for循环中使用延迟的方法

时间:2019-03-28 14:36:19

标签: jquery ajax jquery-deferred

我试图拉回几组统计数据并在每组数据均已加载到DOM后显示进度消息。

我正在尝试使用多个deferreds以及setTimeout函数来管理对用户的响应。

我开始调用一个函数来显示我的加载消息。然后,我使用AJAX检索数据。然后,成功函数将遍历数据集和:

  1. 在stat变量中定义当前数据集
  2. 调用loadDomElement函数(请参见下面的说明),该函数返回一个Promise
  3. 将返回的诺言放入我的诺言数组中
  4. 使用.apply函数传递promise数组,并在完成所有promise后,隐藏加载块以显示所有已在后台加载的元素。
$(function() {

        displayMyWaiter('Fetching month end statistics for all pitches....');

        $.ajax ( {
            url: '../../ajax/stats.php',
            method: 'GET',
            data: {mode: 'all statistics for ent',  statEntity: 'pitch', statType: 'total', statFilter: 'distinct'},
            dataType: 'json',
            type: 'POST',
            success: function(statGroup){
                console.log(statGroup);

                var promises = [];

                for (var i in statGroup) {

                    var stat = statGroup[i];
                    console.log(stat);
                    var def = $.Deferred();

                    $.when( loadDomElement(stat) ).done(function() {
                        console.log( "hello" );
                        def.resolve();
                        promises.push(def);
                    });

                };

                $.when.apply($, promises).done(function() {
                    hideMyWaiter("slide");
                });

            }       
        });        
    });

loadDomElement函数将当前状态作为参数传递给它,并返回一个Promise。它实际上是在我的页面上添加了一个html块。然后,它调用loadStat函数,该函数还返回一个promise-它解决了loadDomElement函数中的延迟问题。代码如下:

function loadDomElement(stat) {
        var dfd = $.Deferred();
        var statPanelID = 'stat_block_' + stat.code;
        $('#stats').append( '<div id="' + statPanelID + '"></div>' );

        $.when( loadStat(statPanelID, stat) ).done(function() {
            dfd.resolve();
        });

        return dfd.promise()
    }

loadStat函数从创建一个externalDef延迟变量开始。然后,它调用我的函数来更新Loading块中的消息。这将返回一个承诺:

function updateMyWaiter(str) {

        var text = "<li class='waiter-item'>" + str + "</li>"
        var dfd = $.Deferred();
        setTimeout(function(){ 
            $('.busyText').append(text);
            dfd.resolve();
        }, 3000);
        return dfd.promise();
    }

当返回承诺时,它随后调用我的面板函数(该函数也返回一个承诺)并使用我的自定义插件将统计数据加载到页面上(在“加载”消息之后)。该函数如下所示:

function loadStat(statPanelID, stat) {

        console.log("Now create stats for " + stat.code + ": " + stat.desc + " and place it in this block: " + statPanelID);
        var outerDef = $.Deferred();

        $.when( updateMyWaiter("Loading stats for " + stat.desc + "( code: " + stat.code + ")") ).done(function() {

            var panel = function() {

                var d = $.Deferred();
                var panelTitle = (stat.desc === null ? 'Pitch ' + stat.code : stat.desc);
                var statPluginID = 'stat_' + stat.code;

                $("#" + statPanelID).panIt({
                    allowScrolling: false,
                    header: {
                        title: panelTitle
                    },
                    body: {
                        content: '<div id="' + statPluginID + '">Position stat plugin for ' + stat.desc + ' here.</div>',
                        height:  '700'                                
                    },
                    onLoaded: function() {
                        $.when ( $('#' + statPluginID).stats({ // dom ID for stat plugin
                            statEntity: 'pitch',
                            statEntityID: stat.code,
                            statType: 'total',
                            statPeriod: null,
                            chartType: 'line',
                            chartTitle: 'Pitch stats for: ' + stat.desc,
                            activeTab: 'chart',
                            clickOptions: {
                                enabled: false
                            },
                            chartHeight: 700,
                            table: {
                                headers: [
                                    { name: 'Month', data: 'month' },
                                    { name: 'BF', data: 'bf' },
                                    { name: 'New', data: 'new_mem' },
                                    { name: 'Trn In', data: 'tra_in' },
                                    { name: 'Trn Out', data: 'tra_out' },
                                    { name: 'Lapsed', data: 'lapsed' },
                                    { name: 'CF', data:   'cf' },
                                    { name: 'Balance', data: 'balance'}
                                ],
                                hasSelect:  false,
                                search: false
                            }
                        })).done (function(result) {
                            d.resolve ('Pitch stats: ' + result);
                        });
                    }
                });
                return d.promise();

            };

            $.when ( panel() ).done (function(result) {
                console.log(result);
                outerDef.resolve(result); 
            });

        });

        return outerDef.promise();
    }

我本质上希望应用程序以我最初的消息开头:“正在获取所有音调的月末统计信息...。”,然后对于每个统计信息,它都应该使用anotehr行更新加载消息,该行指出现在正在加载哪个统计信息。加载所有统计信息后,应隐藏加载消息。

但是发生的是,我收到了初始消息,该消息仅在隐藏之前显示一秒钟。然后,应用程序继续将数据加载到DOM。

1 个答案:

答案 0 :(得分:0)

我在另一个日志中找到了答案:click here

我对代码进行了如下调整:

$(function() {

        displayMyWaiter('Fetching month end statistics for all pitches....');

        $.ajax ( {
            url: '../../ajax/stats.php',
            method: 'GET',
            data: {mode: 'all statistics for ent',  statEntity: 'pitch', statType: 'total', statFilter: 'distinct'},
            dataType: 'json',
            type: 'POST',
            success: function(statGroup){
                handlePitchData(statGroup, 0); 
            }        
        });        

    });

function handlePitchData(statGroup, i) {

        if(i<statGroup.length){
            var stat = statGroup[i];
            console.log(statGroup[i]);
            $.when( loadDomElement(stat) ).done(function() {
                handlePitchData(statGroup, i+1);
            });    
        } else {
            hideMyWaiter("slide");
        }

    }



    function loadDomElement(stat) {
        var dfd = $.Deferred();
        var statPanelID = 'stat_block_' + stat.code;
        $('#stats').append( '<div id="' + statPanelID + '"></div>' );

        $.when( updateMyWaiter("Loading stats for " + stat.desc), loadStat(statPanelID, stat) ).done(function() {
            dfd.resolve();;
        });

        return dfd.promise();
    }

function loadStat(statPanelID, stat) {

        console.log("Now create stats for " + stat.code + ": " + stat.desc + " and place it in this block: " + statPanelID);
        var outerDef = $.Deferred();

        var panel = function() {

            var d = $.Deferred();
            var panelTitle = (stat.desc === null ? 'Pitch ' + stat.code : stat.desc);
            var statPluginID = 'stat_' + stat.code;

            $("#" + statPanelID).panIt({
                allowScrolling: false,
                header: {
                    title: panelTitle
                },
                body: {
                    content: '<div id="' + statPluginID + '">Position stat plugin for ' + stat.desc + ' here.</div>',
                    height:  '700'                                
                },
                onLoaded: function() {
                    $.when ( $('#' + statPluginID).stats({ // dom ID for stat plugin
                        statEntity: 'pitch',
                        statEntityID: stat.code,
                        statType: 'total',
                        statPeriod: null,
                        chartType: 'line',
                        chartTitle: 'Pitch stats for: ' + stat.desc,
                        activeTab: 'chart',
                        clickOptions: {
                            enabled: false
                        },
                        chartHeight: 700,
                        table: {
                            headers: [
                                { name: 'Month', data: 'month' },
                                { name: 'BF', data: 'bf' },
                                { name: 'New', data: 'new_mem' },
                                { name: 'Trn In', data: 'tra_in' },
                                { name: 'Trn Out', data: 'tra_out' },
                                { name: 'Lapsed', data: 'lapsed' },
                                { name: 'CF', data:   'cf' },
                                { name: 'Balance', data: 'balance'}
                            ],
                            hasSelect:  false,
                            search: false
                        }
                    })).done (function(result) {
                        d.resolve ('Pitch stats: ' + result);
                    });
                }
            });
            return d.promise();

        };

        $.when ( panel() ).done (function(result) {
            console.log(result);
            outerDef.resolve(result); 
        });

        return outerDef.promise();
    }


简而言之,我使用了递归方法。