在.then()承诺

时间:2018-02-14 13:48:05

标签: javascript jquery arrays json

目标:如果html元素数量超过现有JSON文件的数组,则在JSON中创建数组。然后,获取每个数组的.length并添加到将附加到html的btn

我有一个脚本,它开始检测我的页面上有多少postWrapper元素,然后循环遍历它们并确定commentslikesviews(存储三个外部JSON文件的三个变量都具有每个索引postWrapper元素的相应数组。如果其中一个JSON文件中不存在该数组,则postArray()函数进行$.ajax调用,php将空数组写入每个JSON文件的末尾。然后,您会看到我使用.push([])将空数组添加到现有的commentslikesviews变量中,以便它们也反映更新的JSON文件

我正在使用.then()来确保其中一些功能同步执行。 之后,JSON文件已经更新并且空数组已被推送到现有的js变量,然后我需要在我的postWrapper函数的帮助下将按钮附加到injectBtn()元素。此函数读取commentslikesviews变量以确定数组的.length,然后添加计数,如果愿意的话。

我面临的问题是,如果这三个JSON文件中的一个没有足够数量的数组,postArray()函数似乎成功执行(因此更新了JSON文件),但是js获得.push([])方法的变量在injectBtn()尝试执行并获取新创建的数组的.length之前不会更新。然后我留下以下错误:

  

jQuery.Deferred异常:无法读取属性'includes'的未定义TypeError:无法读取未定义的属性'includes'

如何解决此问题,以便在comments尝试阅读likes之前更新我的JSON文件和viewsinjectBtn().length变量包含在其中的数组?

我的代码如下(至少我认为相关的部分)。如果您有任何疑问或需要更多背景信息,请与我们联系。

    var postArray = function() {

        return $.ajax({
            type: "post",
            url: "/php/api.php",
            dataType: "text",
            data: {
                array: "new"
            }
        });

    }

    var injectBtns = function(element, index) {
        $(element[index]).append(
            "<a class='js comment btn' href='#' title='Comment'>" +
                "<span class='js comment count'>" + comments[index].length + "</span>" +
                "<svg class='icon' width='16px' height='16px' viewbox='0 0 16 16'>" +
                    "<use xlink:href='/assets/icons.svg#comments'></use>" +
                "</svg>" +
            "</a>" +
            "<a class='js like btn' href='#' title='Like'>" +
                "<span class='js like count'>" + likes[index].length + "</span>" +
                "<svg class='icon' width='16px' height='16px' viewbox='0 0 16 16'>" +
                    "<use xlink:href='/assets/icons.svg#likes'></use>" +
                "</svg>" +
            "</a>" +
            "<a class='js view btn' href='#' title='Like'>" +
                "<span class='js view count'>" + views[index].length + "</span>" +
                "<svg class='icon' width='16px' height='16px' viewbox='0 0 16 16'>" +
                    "<use xlink:href='/assets/icons.svg#views'></use>" +
                "</svg>" +
            "</a>"
        );
    }

    var postWrapper = $(".js.post.wrapper"),
        commentBtn = ".js.comment.btn",
        likeBtn = ".js.like.btn",
        viewBtn = ".js.view.btn";

    for (var i = 0; i < $(postWrapper).length; i++) {

        (function(index) {

            if (typeof comments[index] === "undefined" || typeof likes[index] === "undefined" || typeof views[index] === "undefined") {

                postArray().then(function() {
                    comments.push([]);
                    likes.push([]);
                    views.push([]);

                    injectBtns(postWrapper, index);
                });
            } else {
                injectBtns(postWrapper, index);
            }

        })(i);

        if (comments[i].includes(client)) {
            $(postWrapper[i]).children(commentBtn).addClass("active");
        }

        if (likes[i].includes(client)) {
            $(postWrapper[i]).children(likeBtn).addClass("active");
            $(postWrapper[i]).children(likeBtn).prop("title", "Unlike");
        }

        if (views[i].includes(client)) {
            $(postWrapper[i]).children(viewBtn).addClass("active");
        }

    }

1 个答案:

答案 0 :(得分:2)

  

如何解决这个问题,以便在injectBtn()尝试读取其中包含的.length数组之前更新我的JSON文件和注释,喜欢和视图变量?

您还需要将它们放在then回调中。

for (var i = 0; i < $(postWrapper).length; i++) {
    (function(i) {

        var promise = (typeof comments[i] === "undefined" || typeof likes[i] === "undefined" || typeof views[i] === "undefined")
          ? postArray().then(function() {
                comments.push([]);
                likes.push([]);
                views.push([]);
            })
          : $.when(undefined);

        promise.then(function() {
            injectBtns(postWrapper, i);

            if (comments[i].includes(client)) {
                $(postWrapper[i]).children(commentBtn).addClass("active");
            }

            if (likes[i].includes(client)) {
                $(postWrapper[i]).children(likeBtn).addClass("active");
                $(postWrapper[i]).children(likeBtn).prop("title", "Unlike");
            }

            if (views[i].includes(client)) {
                $(postWrapper[i]).children(viewBtn).addClass("active");
            }
        });
    })(i);
}

请注意,整个方法非常糟糕

  • 为了防范竞争条件,你不应该只是要求制作一个新阵列(最后)&#34;而是#34;在i位置制作一个数组(如果它还没有存在)&#34;。
  • 您应该制作一个具有预期数组数量的简单请求(即postWrapper.length),而不是发出多个请求(每个丢失数组一个)。然后php脚本应该生成尽可能多的数据。
  • 您根本不应该使用客户端脚本,甚至不接受发出个别评论/喜欢/查看部分的请求(这是一个巨大的安全风险)。 php服务器应该知道哪个帖子在哪个页面上,并且首先为json提供正确数量的数组。