如何循环关联数组并在块之间延迟显示数据块

时间:2016-08-27 00:39:29

标签: javascript promise delayed-execution

我正在努力在页面上展示生日。我想要实现的是将部门作为标题,然后在其下显示3个生日并循环显示部门,直到显示所有生日(延迟5秒以便可以阅读),然后继续到下一个部门

我在jsFiddle上有一个示例,这是我的大部分代码:

$.wait(3000, function() {
    $(".action-area").animate({
    'visibility': 'visible'
    }, 2000, function() {
    $(".action-area").fadeIn().removeClass('hidden');
    presentMultipleData(_birthdayData, 5);
    });
});

var _chunkLimit = 3;

function presentMultipleData(data, limit) {
    for (var key in data) {
    if (data.hasOwnProperty(key)) {
        // Chunk out the array to only show a specific count
        var chunkArray = chunk(_chunkLimit, data[key]);
        $("h1.department").text(key);
        // Chunk group
        for (var i = 0, len = chunkArray.length; i < len; i++) {
            // Empty for new group to be shown
            $("#item-list").empty();
            // Add group items
            _addGroupItems(chunkArray[i]);
            // @todo Need to delay after each chunk is added so it is presented for 5 seconds
            // then go to the next group
        }
    }
    }
}

function _addGroupItems(data) {
    for (var i = 0, len = data.length; i < len; i++) {
    var _item = buildItem(data[i]);
    $("#item-list").append(_item);
    }
}

function buildItem(row) {
    var _item = $('<div/>', {
    'class':'item',
    'text': row['name']+' - '+row['date'],
    });

    return _item;
}

function chunk(chunkSize, array) {
    return array.reduce(function(previous, current) {
    var chunk;
    if (previous.length === 0 || previous[previous.length -1].length === chunkSize) {
        chunk = [];
        previous.push(chunk);
    }
    else {
        chunk = previous[previous.length -1];
    }
    chunk.push(current);
    return previous;
    }, []);
}

我能够遍历所有内容,并且逻辑是在那里构建项目并呈现它们......我的问题是延迟5秒然后继续。

我认为for循环导致了这里的问题,因为我更多地关注Promises和Deffered示例。我在这类事情上看到很多关于SO的主题,但看不到能满足我需求的主题。

正如你在我的演示中所看到的,它会运行,但你唯一看到的是最后一个结果,即最后一个部门和最后三个人。我已经尝试了许多不同的方法,并将它们从代码中清除,因为没有任何效果。我暂时没有使用过JavaScript,所以当我尝试使用Promise时,我没有成功,不确定它们是否应该以这种方式使用。

我只需要朝着正确的方向努力。希望有人可以提供帮助。感谢

1 个答案:

答案 0 :(得分:1)

你可以使用Promise和array#reduce

来实现你想要的

reduce回调的每次迭代都会返回一个5秒后解析的promise。回调“等待”这个承诺,如promise.then(....)(承诺是前一次迭代中返回的承诺

你在数组中基本上有一个数组,所以你在“departments”中嵌套“chunk”减少

当整个事情完成时,工作片段还会将“全部完成”记录到控制台。这是通过从外部reduce返回promise并将{.then添加到presentMultipleData调用

来实现的

    var _birthdayData = JSON.parse('{"Admin Operations":[{"name":"Blanca Tirado","date":"08\/26","department":"Admin Operations","position":"Reporter"}],"Customer Service":[{"name":"Perla Mendoza","date":"08\/26","department":"Customer Service","position":"Receptionist"},{"name":"Jeanette Lopez","date":"08\/30","department":"Customer Service","position":"Customer Service Rep"}],"Onion AM":[{"name":"Eutimio Merida","date":"08\/28","department":"Onion AM","position":"Onion Peeler"}],"Prep":[{"name":"Carlos Segovia","date":"08\/27","department":"Prep","position":"WIP"},{"name":"Margarita Rodriguez","date":"08\/29","department":"Prep","position":"WIP"},{"name":"Orlin Fuentes Nunes","date":"08\/29","department":"Prep","position":"WIP"},{"name":"Fairy Garcia","date":"09\/04","department":"Prep","position":"WIP"},{"name":"Mireya Lomeli","date":"09\/09","department":"Prep","position":"WIP"}],"Production 1":[{"name":"Jesus Alvarado","date":"09\/01","department":"Production 1","position":"Line Worker"},{"name":"Rosa Jimenez","date":"09\/03","department":"Production 1","position":"Line Worker"},{"name":"Natividad Jacuinde","date":"09\/08","department":"Production 1","position":"Line Worker"}],"Production 2":[{"name":"Juventino Sanchez","date":"09\/01","department":"Production 2","position":"Equipment Operator"},{"name":"Deysi Garcia","date":"09\/02","department":"Production 2","position":"Specialist"},{"name":"Aristeo Medina","date":"09\/03","department":"Production 2","position":"Line Worker"}],"Quality Assurance":[{"name":"Martha Lopez","date":"08\/31","department":"Quality Assurance","position":"QA Tech 2"},{"name":"Juana Robledo","date":"09\/01","department":"Quality Assurance","position":"QA Tech 2"}],"Retail B":[{"name":"Luz Cruz","date":"08\/26","department":"Retail B","position":"Specialist"}],"Retail C":[{"name":"Rosalina Lopez","date":"08\/30","department":"Retail C","position":"Specialist"}],"Sanitation":[{"name":"Yajaira Medina","date":"08\/26","department":"Sanitation","position":"Sanitation Tech 1"},{"name":"Luis Mendez Lopez","date":"08\/31","department":"Sanitation","position":"Sanitation Tech 1"}],"Warehouse":[{"name":"Ramon Cardenas","date":"08\/27","department":"Warehouse","position":"Warehouse Tech 1"},{"name":"Ramon Amezquita","date":"08\/28","department":"Warehouse","position":"Warehouse Tech 1"},{"name":"Juan Sayula","date":"09\/02","department":"Warehouse","position":"Shipping Tech"}]}');


jQuery(function($) {

        $.wait = function(duration, completeCallback, target) {
            $target = $(target || '<queue />');
            return $target.delay(duration).queue(function(next){completeCallback.call($target); next();});
        }

        $.fn.wait = function(duration, completeCallback) {
            return $.wait.call(this, duration, completeCallback, this);
        };


        $.wait(3000, function() {
            $(".action-area").animate({
                'visibility': 'visible'
            }, 2000, function() {
                $(".action-area").fadeIn().removeClass('hidden');
                presentMultipleData(_birthdayData, 5).then(function() {
                    console.log('all done');
                });
            });
        });

        var _chunkLimit = 3;
                   
        function presentMultipleData(data, limit) {
            var pdelay = function() {
                return new Promise(function(resolve) {
                    setTimeout(resolve, 5000);
                })
            };
            return Object.keys(data).reduce(function(promise, key) {
                return promise.then(function() {
                    // Chunk out the array to only show a specific count
                    var chunkArray = chunk(_chunkLimit, data[key]);
                    $("h1.department").text(key);
                    return chunkArray.reduce(function(promise, chunk) {
                        return promise.then(function() {
                            $("#item-list").empty();
                            _addGroupItems(chunk);
                            return pdelay();
                        });
                    }, Promise.resolve());
                });
            }, Promise.resolve());
        }
        function _addGroupItems(data) {
            for (var i = 0, len = data.length; i < len; i++) {
                var _item = buildItem(data[i]);
                $("#item-list").append(_item);
            }
        }

        function buildItem(row) {
            var _item = $('<div/>', {
                'class':'item',
                'text': row['name']+' - '+row['date'],
            });

            return _item;
        }

        function chunk(chunkSize, array) {
            return array.reduce(function(previous, current) {
                var chunk;
                if (previous.length === 0 || previous[previous.length -1].length === chunkSize) {
                    chunk = [];
                    previous.push(chunk);
                }
                else {
                    chunk = previous[previous.length -1];
                }
                chunk.push(current);
                return previous;
            }, []);
        }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="cage">
    <div class="action-area hidden">
        <div class="modal-window">
            <h1 class="department"></h1>
            <div id="item-list" class="modal-content"></div>
        </div>
    </div>
</div>

  

非jquery,es2015 +版

var _birthdayData = JSON.parse('{"Admin Operations":[{"name":"Blanca Tirado","date":"08\/26","department":"Admin Operations","position":"Reporter"}],"Customer Service":[{"name":"Perla Mendoza","date":"08\/26","department":"Customer Service","position":"Receptionist"},{"name":"Jeanette Lopez","date":"08\/30","department":"Customer Service","position":"Customer Service Rep"}],"Onion AM":[{"name":"Eutimio Merida","date":"08\/28","department":"Onion AM","position":"Onion Peeler"}],"Prep":[{"name":"Carlos Segovia","date":"08\/27","department":"Prep","position":"WIP"},{"name":"Margarita Rodriguez","date":"08\/29","department":"Prep","position":"WIP"},{"name":"Orlin Fuentes Nunes","date":"08\/29","department":"Prep","position":"WIP"},{"name":"Fairy Garcia","date":"09\/04","department":"Prep","position":"WIP"},{"name":"Mireya Lomeli","date":"09\/09","department":"Prep","position":"WIP"}],"Production 1":[{"name":"Jesus Alvarado","date":"09\/01","department":"Production 1","position":"Line Worker"},{"name":"Rosa Jimenez","date":"09\/03","department":"Production 1","position":"Line Worker"},{"name":"Natividad Jacuinde","date":"09\/08","department":"Production 1","position":"Line Worker"}],"Production 2":[{"name":"Juventino Sanchez","date":"09\/01","department":"Production 2","position":"Equipment Operator"},{"name":"Deysi Garcia","date":"09\/02","department":"Production 2","position":"Specialist"},{"name":"Aristeo Medina","date":"09\/03","department":"Production 2","position":"Line Worker"}],"Quality Assurance":[{"name":"Martha Lopez","date":"08\/31","department":"Quality Assurance","position":"QA Tech 2"},{"name":"Juana Robledo","date":"09\/01","department":"Quality Assurance","position":"QA Tech 2"}],"Retail B":[{"name":"Luz Cruz","date":"08\/26","department":"Retail B","position":"Specialist"}],"Retail C":[{"name":"Rosalina Lopez","date":"08\/30","department":"Retail C","position":"Specialist"}],"Sanitation":[{"name":"Yajaira Medina","date":"08\/26","department":"Sanitation","position":"Sanitation Tech 1"},{"name":"Luis Mendez Lopez","date":"08\/31","department":"Sanitation","position":"Sanitation Tech 1"}],"Warehouse":[{"name":"Ramon Cardenas","date":"08\/27","department":"Warehouse","position":"Warehouse Tech 1"},{"name":"Ramon Amezquita","date":"08\/28","department":"Warehouse","position":"Warehouse Tech 1"},{"name":"Juan Sayula","date":"09\/02","department":"Warehouse","position":"Shipping Tech"}]}');

document.addEventListener("DOMContentLoaded", e => {
    var _chunkLimit = 3,
        pdelay = timeout => new Promise(resolve => setTimeout(resolve, timeout)),
        buildItem = row => {
            var div = document.createElement('div');
            div.classname = 'item';
            div.appendChild(document.createTextNode(row.name+' - '+row.date));
            return div;
        },
        _addGroupItems = data => data.map(item => buildItem(item)).forEach(item => document.getElementById("item-list").appendChild(item)),
        toChunk = (chunkSize, array) => array.reduce((previous, current) => {
            var chunk;
            if (previous.length === 0 || previous[previous.length -1].length === chunkSize) {
                chunk = [];
                previous.push(chunk);
            }
            else {
                chunk = previous[previous.length -1];
            }
            chunk.push(current);
            return previous;
        }, []),
        presentMultipleData = (data, limit) => Object.keys(data).reduce((promise, key) => promise.then(() => {
            // Chunk out the array to only show a specific count
            var chunkArray = toChunk(_chunkLimit, data[key]);
            document.querySelector("h1.department").textContent = key;
            return chunkArray.reduce((promise, chunk) => promise.then(() => {
                document.getElementById("item-list").innerHTML = '';
                _addGroupItems(chunk);
                return pdelay(5000);
            }), Promise.resolve());
        }), pdelay(5000));
        
    presentMultipleData(_birthdayData, 5).then(() => console.log('all done'));
});
<div id="cage">
    <div class="action-area hidden">
        <div class="modal-window">
            <h1 class="department"></h1>
            <div id="item-list" class="modal-content"></div>
        </div>
    </div>
</div>