jQuery向Node.js服务器发出的Ajax请求仅在页面刷新时有效

3

我对AJAX很陌生,不确定问题出在哪里。我的网页通过AJAX get请求获取帖子上的所有评论。问题是,只有在刷新页面后才能成功完成AJAX请求。我禁用了缓存以查看是否解决了问题,但并没有。

例如,当我从A帖子刷新页面获取第一条评论,然后转到网站上的B帖子时,A帖子的评论会显示为B帖子的评论。之后,当我刷新页面时,B帖子的评论被成功替换成B帖子的评论。

我正在使用jQuery进行请求:

$.ajax({
    type: "GET",
    url: someURL,
    success: (comments) => {
        console.log(comments);
    
        comments.questions.forEach(questionComment => {
            $('.questionComments').append(
                `<div class="comment">
                    <p>${questionComment.content}</p>
                </div>
                `
            )
        });
    
    
        comments.answers.forEach(answer => {
            answer.forEach(answerComment => {
                $(`.answer#${answerComment.forId} .answerComments`).append(
                    `<div class="comment">
                    <p>${answerComment.content}</p>
                </div>
                `
                )
            })
        })
    },
    cache: false
})

服务器端:(express.js,mongoose)

let allComments = {}
app.get('/questions/:questionID/getComments', (req, res) => {

       if (err) return console.error(err)

    Comment.find({ forQuestion: true, forId: req.params.questionID }, (err, questionComments) => {
        allComments['questions'] = questionComments 
    })


    Answer.find({ questionId: req.params.questionID }, (err, answers) => {
        if (err) return console.error(err);
        allAnswerComments = []
        answers.forEach(answer => {
            Comment.find({ forAnswer: true, forId: answer._id }, (err, comments) => {
                allAnswerComments.push(comments)
            })
        });

        allComments['answers'] = allAnswerComments

    })

    res.send(allComments)

})


在重新加载前,评论对象是空对象。 blank object 在重新加载后,评论对象如下图所示。enter image description here 当你跳转到不同的帖子 / 不同的URL时,来自上一个帖子 / URL的对象是新帖子上的初始对象,然后当你重新加载页面时,正确的对象被获取。

3
你肯定是在某个特殊的上下文中编写这段代码,比如一个函数或其他什么东西。这段代码不足以弄清楚问题出在哪里。 - Jeremy Thille
3
请提供一个 [mcve](最小化、完整、可复现的示例),以便更好地理解和解决您的问题。 - Andreas
@Andreas 你需要更多的代码吗? - koder613
@JeremyThille 你需要更多的代码吗? - koder613
@JeremyThille 我明白,但是ajax请求“记住”了上一个请求的数据,甚至在原始页面加载时也无法正确获取评论。 - koder613
显示剩余11条评论
3个回答

1
根据您的描述,当执行AJAX请求时它可以工作,但问题在于它只会在页面加载时执行一次。让我们编写一个函数来解决这个问题:
function sendAJAX() {
$.ajax({
    type: "GET",
    url: someURL,
    success: (comments) => {
        console.log(comments);
    
        comments.questions.forEach(questionComment => {
            $('.questionComments').append(
                `<div class="comment">
                    <p>${questionComment.content}</p>
                </div>
                `
            )
        });
    
    
        comments.answers.forEach(answer => {
            answer.forEach(answerComment => {
                $(`.answer#${answerComment.forId} .answerComments`).append(
                    `<div class="comment">
                    <p>${answerComment.content}</p>
                </div>
                `
                )
            })
        })
    },
    cache: false
})
}

并确保它定期被调用:

sendAJAX();
seInterval(sendAJAX, 10000);

这仍然是不正确的,因为它会每十秒钟添加所有评论。为了改进这一点,您可以添加一个表示上次请求时刻的值,并在服务器端加载仅在该时刻和当前时刻之间创建的评论。


@koder613 我的意思是使用 setInterval。请再次测试并至少等待一分钟。 - Lajos Arpad
我使用 setInterval 进行了重新测试。现在,第一个 AJAX 调用返回一个空对象(10秒后),第二个 AJAX 调用包含正确的数据(20秒后)。这是在我重新启动 nodejs 服务器后发生的。然后当我转到另一篇文章时,10秒后来自上一篇文章的 AJAX 响应显示出来,20秒后正确的响应被显示。所以问题还没有解决,什么也没有改变。感谢您的帮助。 - koder613
@koder613,我已经编辑了我的答案,以确保它在页面加载时发送请求。 - Lajos Arpad
所以我认为你是对的,肯定是服务器出了问题,因为一个 AJAX 请求没有返回任何数据,只有第二个 AJAX 请求才返回数据。在网络选项卡中,请求每 10 秒发送一次,这是应该的。 - koder613
让我们在聊天中继续这个讨论 - koder613
显示剩余3条评论

0

请描述一下您对获取参数的工作方式,您是如何设置它的?那里是否涉及到任何 cookie?告诉我们 get 评论肯定会帮助我们找出问题,不过使用 sendAjax() 函数而不是在 open Script 中编写 ajax 是个好主意。另一方面,我绝不建议您使用 setInterval(sendAJAX, 10000);相反,请安装一个服务工作者,并在添加新评论时从 API 回传它。然后它应该只获取最后一个评论并将其放在您的评论部分中。


0
根据您的描述,似乎主要问题是A帖子的评论出现在B帖子的评论中。
现在,提供的数据很少,通过查看您的代码,我假设在从A帖子切换到B帖子时,您没有以编程方式刷新页面。
因此,您问题的根本原因是append。您正在将数据附加到div中。因此,在foreach循环之前,首先使用以下方法清除html:

$('.questionComments').html("")

对于答案,请将其替换为以下内容

comments.answers.forEach(answer => {
        let first = true;
            answer.forEach(answerComment => {
            if(first) {
              $(`.answer#${answerComment.forId} .answerComments`).html("")
              first = false;
            }
            
                $(`.answer#${answerComment.forId} .answerComments`).append(
                    `<div class="comment">
                    <p>${answerComment.content}</p>
                </div>
                `
                )
            })
        })

上面的代码片段只是为了演示您必须在添加第一个注释时进行标识,然后重置它。

我还没有测试过这个代码片段,但我希望您已经了解了代码中的问题所在。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接