简体   繁体   中英

jquery ajax request to nodejs server only works on page refresh

I am quite new to AJAX and I am not sure what I am doing wrong. I have a webpage that fetches all comments on a post with an AJAX get request. The issue is that the AJAX request is only successful after the webpage is refreshed. I disabled the cache to see if that would solve the issue, but it didn't.

For example, when I fetch the first comments after refreshing the page from post A and then go onto post B on the website, the comments from the post A appear as the comments for post B, then when I refresh the page the comments for post B are replaced with post B's comments successfully.

I am using jQuery to make the request:

$.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
})

Server-Side: (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)

})

What the commets object looks like before the reload - a blank object空白对象

What the comments object looks like after the reload在此处输入图片说明

When you navigate to a different post / different URL, the object from the previous post / URL is the initial object on the new post, and then when you reload the page the correct object is fetched.

According to your description, the AJAX request works when executed, but the problem is that it's executed only once, at page load. Let's write a function for this purpose:

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
})
}

And ensure that it's called periodically:

sendAJAX();
seInterval(sendAJAX, 10000);

This will still be incorrect, because it will add all comments every ten seconds. To improve this, you could add a value representing the moment of the last request and on server-side load only the comments that were created between that moment and the current one.

Can you please describe your working on get parameters how are you setting it.Is there any cookie involved there? Telling the get comment will definitely help us to figure our the problem how ever sendAjax() function will be great idea instead of writing ajax in open Script. On other side I will never recommend you seInterval(sendAJAX, 10000); instead install a service worker and hit it back from your API when new comment is added. And then it should only fetch the last one and put it in your comment section.

As per your description it seems that the main problem is comment of Post A are appearing in comment of Post B.

Now, there is minimal data provided and by looking and your code, I am assuming that you are not refreshing page programmatically when switching from Post A to Post B.

So, the root cause of your problem is append . You are appending data to your div's. So, before your foreach loops, first clear the html using

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

And for the answers replace it as below

 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> ` ) }) })

The above snippet is just to demonstrate that you have to identify when the first comment is added and then reset it.

I haven't tested the snippet but I hope you got an idea what is wrong in the code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM