【问题标题】:How do I use a deferred in a for loop如何在 for 循环中使用延迟
【发布时间】:2019-08-19 09:10:00
【问题描述】:

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

我正在尝试使用多个延迟和 setTimeout 函数来管理对用户的响应。

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

  1. 在统计变量中定义当前数据集
  2. 调用 loadDomElement 函数(参见下面的解释),该函数返回一个承诺
  3. 将返回的 Promise 推送到我的 Promise 数组中
  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 函数将当前状态作为参数传递给它并返回一个承诺。它本质上是在我的页面上附加了一个 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 函数首先创建一个 outerDef 延迟变量。然后它调用我的函数来更新 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();
    }

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

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。

【问题讨论】:

  • 你需要使用promise对象javascript.info/promise-basics
  • @Taplar 哎呀,我被委派和延期混在一起了,需要眼镜吗????
  • 谢谢@Hogan。只是为了澄清一下,您是说这不能使用 JQuery deferred 来完成,还是只是说 Promise 更容易或更好地使用?谢谢

标签: jquery ajax jquery-deferred


【解决方案1】:

我在另一个日志中找到了答案: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();
    }


总之,我用的是递归的方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多