【问题标题】:jquery ajax request to nodejs server only works on page refresh对nodejs服务器的jquery ajax请求仅适用于页面刷新
【发布时间】:2021-01-09 22:52:03
【问题描述】:

我对 AJAX 很陌生,我不确定自己做错了什么。我有一个网页,可以通过 AJAX 获取请求获取帖子上的所有 cmets。问题是AJAX请求只有在网页刷新后才能成功。我禁用了缓存以查看是否可以解决问题,但它没有。

例如,当我从帖子 A 刷新页面后获取第一个 cmets,然后转到网站上的帖子 B,帖子 A 中的 cmets 显示为帖子 B 的 cmets,然后当我刷新页面时帖子 B 的 cmets 已成功替换为帖子 B 的 cmets。

我正在使用 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、猫鼬)

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)

})

commets 对象在重新加载之前的样子 - 一个空白对象

重新加载后cmets对象的样子

当您导航到不同的帖子/不同的 URL 时,上一个帖子/URL 中的对象是新帖子的初始对象,然后当您重新加载页面时,会获取正确的对象。

【问题讨论】:

  • 你肯定是在一些特殊的上下文中写的,比如一个函数什么的。代码不足以找出问题所在
  • @Andreas 你需要更多代码吗?
  • @JeremyThille 您需要更多代码吗?
  • 好吧,您似乎将它们全部设置为页面$('.questionComments').append( 上的所有.questionComments,这与您使用ID 的另一个不同......

标签: javascript jquery node.js ajax


【解决方案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);

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

【讨论】:

  • 首先,setTimeout 函数不会在 10 秒后只运行一次,它不是一个持续循环吗?其次,澄清一下,我的 AJAX 响应仅在重新加载/刷新后接收数据,因此将函数置于超时状态并不能解决问题。我测试过了。
  • @koder613 我的意思是 setInterval。请再次测试并等待至少一分钟。
  • 我使用setInterval 重新测试。现在,第一个 AJAX 调用返回一个空对象(10 秒后),第二个 AJAX 调用包含正确的数据(20 秒后)。这发生在我重新启动 nodejs 服务器之后。然后,当我转到另一篇文章时,10 秒后显示上一篇文章的 AJAX 响应,20 秒后显示正确响应。所以问题没有解决,没有任何改变。感谢您的帮助
  • @koder613 我已经编辑了我的答案,以确保它也在页面加载时发送请求。
  • @koder613 我的回答是假设您工作的服务器端运行正常。如果没有,那么您可能想问一个不同的问题。您需要查看浏览器开发工具的网络选项卡。如果每 10 秒发送一个请求,那么至少发送部分工作。您可能希望在“网络”选项卡中检查您发送的每个请求的服务器答案,看看是否有错误。
【解决方案2】:

您能否描述一下您在获取参数方面的工作,您是如何设置它的。是否涉及任何 cookie?告诉 get 评论肯定会帮助我们弄清楚我们的问题如何 sendAjax() 函数将是一个好主意,而不是在开放脚本中编写 ajax。 另一方面,我永远不会推荐你 seInterval(sendAJAX, 10000);而是安装一个服务工作者并在添加新评论时从您的 API 中回击它。然后它应该只获取最后一个并将其放在您的评论部分。

【讨论】:

    【解决方案3】:

    根据您的描述,主要问题似乎是帖子 A 的评论出现在帖子 B 的评论中。

    现在,提供的数据很少,通过查看您的代码,我假设您在从帖子 A 切换到帖子 B 时没有以编程方式刷新页面。

    所以,问题的根本原因是追加。您正在将数据附加到您的 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>
                    `
                    )
                })
            })

    上面的sn-p只是为了说明你必须识别第一条评论是什么时候添加的,然后重置它。

    我还没有测试过 sn-p,但我希望你知道代码中有什么问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-21
      • 2016-07-31
      相关资源
      最近更新 更多