执行命令bahaviour

时间:2016-07-28 12:11:41

标签: javascript jquery ajax

我正在编写一个函数,在调用时应该使用tile填充页面。瓦片上的数据是从远程DB获取的(因此是AJAX请求)。我也在代码中使用jQuery 3.0。

以下是功能:

function populateDashboard() {
    var tileBlueprint = '<div class="dashboard_tile">\
                    <div class="dashboard_tile_content">\
                        <table class="tile_table">\
                            <tr class="tile_title">\
                                <td>$title</td>\
                            </tr>\
                            <tr class="tile_data">\
                                <td>$value</td>\
                            </tr>\
                        </table>\
                    </div>\
                </div>';

$.ajax({
        url: 'http://' + AppVar.ServerUrl + '/restapi/Dashboard_GetData',
        type: 'POST',
        data: JSON.stringify({
            'SessionId': AppVar.SessionId
        }),
        dataType: 'json',
        contentType: "application/json",
        success: function (data) {
            if (data.ResultCode === '0') {
                //current tiles get wiped
                $('.dashboard_tile').fadeOut(100, function () {
                    $(".tile_handler").empty();
                    console.log("1 - " + Date.now())
                });

                //new tiles are parsed and data is injected into the string which represents the tile
                //tiles are saved into an array
                var json = $.parseJSON(data.TileData);
                var tileArr = [];
                $.each(json.tiles, function (index, element) {
                    tile = tileBlueprint.replace("$title", $.i18n("dashboard-" + element.title));
                    tile = tile.replace("$value", element.value);
                    tileArr[index] = tile;
                    console.log("2 - " + Date.now())
                });

                //now I loop trough the previously created array to populate the page
                $.each(tileArr, function (index, element) {
                    setTimeout(function () {
                        $(element).hide().appendTo(".tile_handler").fadeIn(1000);
                    }, 1000 * index); //delay made longer to see the effect better
                    console.log("3 - " + Date.now())
                });
            } else {
                ons.notification.alert($.i18n('error-retriving_data_problem'));
                return;
            }
        },
        error: function (request, error) {
            ons.notification.alert($.i18n('error-conn_error'));
            return;
        }
    });
}

我不认为注入此内容的HTML是相关的,因为该部分工作正常。

问题在于 fadeout 以及每个循环都会在成功时调用,无法调出callout。我试着记录每次执行的时间,这就是我得到的:

//first run
2 - 1469707068268 (6 times)
3 - 1469707068269 (6 times)
//second run
2 - 1469707181179 (2 times)
2 - 1469707181180 (3 times)
2 - 1469707181181
3 - 1469707181181
3 - 1469707181182 (4 times)
3 - 1469707181183
1 - 1469707181283
1 - 1469707181284 (2 times)
1 - 1469707181285 (2 times)
1 - 1469707181286

我正在显示6个图块,因此评论 2 3 应该点亮6次而 1 只会点击一次。

  • 1 为什么不首先执行?

  • 为什么 1 执行了6次? 编辑:刚才自己想出来。

  • 如果最后执行 1 ,为什么不删除之前创建的所有图块?

另一个问题是,它第一次显示6个图块,但第二次(及以后),它只显示5个图块(首先缺少)。

任何人都可以帮我解释发生了什么,我怎样才能避免这样的行为?

谢谢。

2 个答案:

答案 0 :(得分:3)

  

为什么 1 首先执行,为什么 1 执行6次?

.fadeOut的文档中,第二个参数是“动画完成后调用的函数,每个匹配元素调用一次”。

因此在这种情况下,函数将在~100ms之后调用(您提供的延迟作为第一个参数)并将被调用六次(每个匹配元素一次)。

  

如果最后执行 1 ,为什么不删除之前创建的所有图块?

如上所示, 1 在100ms后运行。但是,实际节点是在1000 * index ms:

之后添加的
setTimeout(function () {
    $(element).hide().appendTo(".tile_handler").fadeIn(1000);
}, 1000 * index);

因此,对于除第一个节点之外的所有节点,实际附加节点的代码都在 1 之后运行。但是,对于第一个节点(注意:索引0 => 1000 * 0 = 0ms延迟),appendTo代码直接运行,这意味着在100ms之后调用.empty()时实际上将删除它。这意味着您只能看到6个节点中的5个。

解决这些问题的方法是以某种方式“同步”代码,使其以您期望的方式运行。这通常是回调的用途,您将完成某些操作后要运行的代码放入回调函数中。在这种情况下,一种解决方案可能是将“添加”代码移动到fadeOut回调中:

$('.dashboard_tile').fadeOut(100).promise().done(function () {
    $(".tile_handler").empty();
    var json = $.parseJSON(data.TileData);
    var tileArr = [];
    $.each(json.tiles, function (index, element) {
        tile = tileBlueprint.replace("$title", $.i18n("dashboard-" + element.title));
        tile = tile.replace("$value", element.value);
        tileArr[index] = tile;
    });
    // ...
});

注意.promise.done的用法,一旦所有元素都完成了动画而不是每个元素都有一个回调,它会给我们一个回调。

答案 1 :(得分:1)

我发现您的代码存在多个问题,因此我可以推荐以下内容:

data: JSON.stringify({
    'SessionId': AppVar.SessionId
}),

应该只是

data: {'SessionId': AppVar.SessionId},

因为jQuery的AJAX函数会为你转换它。

尝试console.log(data.TileData);;如果你已经收到一个JS对象/数组,那么有一个ZERO有理由调用var json = $.parseJSON(data.TileData);所以你应该删除它。

而不是

$.each(json.tiles, function (index, element) {`

使用

$.each(data.TileData.tiles, function (index, element) {

现在,对于最终问题,fadeOut()fadeIn()被调整无序。

试试这个:

// Make sure the fadeOut() finishes before calling more stuff!!!

//current tiles get wiped
$('.dashboard_tile').fadeOut(100, function () {
    $(".tile_handler").empty();
    console.log("1 - " + Date.now())

    //new tiles are parsed and data is injected into the string which represents the tile
    //tiles are saved into an array
    var tileArr = [];
    $.each(data.TileData.tiles, function (index, element) {
        tile = tileBlueprint.replace("$title", $.i18n("dashboard-" + element.title));
        tile = tile.replace("$value", element.value);
        tileArr[index] = tile;
        console.log("2 - " + Date.now())
    });

    //now I loop trough the previously created array to populate the page
    $.each(tileArr, function (index, element) {
        setTimeout(function () {
            $(element).hide().appendTo(".tile_handler").fadeIn(1000);
        }, 1000 * index); //delay made longer to see the effect better
        console.log("3 - " + Date.now())
    });
});