API 或 JavaScript 不一致

API or JavaScript inconsistencies

我的模板中有一个 JS 函数,它与获取命令一起使用以中继到 Django 视图。奇怪的是,大部分时间它都符合预期,但有时它却不符合预期,我不明白为什么。

模板中的 JS:

<script>
    if (document.querySelectorAll(".nav-link")[1].innerHTML != "Log In") {
        var like = document.querySelector(".likes");
        var quantity = document.querySelector(".quantity");
        like.addEventListener("click", () => likes())
        function likes () {
            fetch(`/likes/${like.value}`, {
                method: "PUT"});
            if (like.innerHTML.slice(0, 2) != "Un") {
                like.innerHTML = "Unlike &#128148";
            }
            else {
                like.innerHTML = "Like &#10084";
            }
            fetch(`/likes/${like.value}`)
            .then(response => response.json())
            .then(post => {
                console.log(post["liked"]);
                quantity.innerHTML = post["liked"].length;
            });
        }
    }
</script>

我的看法:

@csrf_exempt
@login_required
def likes(request, id):
    user = User.objects.get(username=request.user)
    try:
        post = Post.objects.get(pk=id)
    except Post.DoesNotExist:
        return JsonResponse({"error": "No such post"}, status=404)
    
    if request.method == "GET":
        return JsonResponse(post.serialize())

    if request.method == "PUT":
        #data = json.loads(request)
        if user not in post.liked.all() and post.poster != user:
            print("adding")
            post.liked.add(user)
            post.save()
        else:
            print("removing")
            post.liked.remove(user)
            post.save()
        return HttpResponse(status=204)

它应该在空列表和包含两个的列表之间交替。

不过大家可以看到,虽然平时可以正常工作,但是有一个地方连续出现几个“[2]”,有时也连续出现几个“[]”。

实际上这只是在添加第二次提取后才开始的,但我不明白为什么;在此之前,它可以毫无问题地交替。

作为@Jared Smith 在评论中说,fetch 的顺序是异步的,因此无法保证顺序,要控制顺序,请使用 asyncawait 等待响应结果,如下所示:

    like.addEventListener("click", async () => await likes())
    async function likes () {
        await fetch(`/likes/${like.value}`, {
            method: "PUT"});
        if (like.innerHTML.slice(0, 2) != "Un") {
            like.innerHTML = "Unlike &#128148";
        }
        else {
            like.innerHTML = "Like &#10084";
        }
        await fetch(`/likes/${like.value}`);
        const post = await response.json();
        quantity.innerHTML = post["liked"].length;
    }