投票数更新问题及 AJAX 解决方法

117 阅读2分钟

在 Google App Engine 中,我们在为博客文章创建投票按钮时可能会遇到以下问题:

huake_00198_.jpg

  • 问题描述:当用户点击投票按钮时,会发送一个 POST 请求到服务器,服务器收到请求后,会更新数据库中的文章投票数,然后重新渲染整个页面。如果用户在此过程中刷新页面,就会看到浏览器的确认表单提交警报。

  • 具体代码:

class Latest(Handler):

    def get(self):
        posts = recent_posts()
        qt = memcache.get('recent_posts_qt')
        if qt:
            qt = time.time() - qt
        self.render('latest.html', articles = posts, qt = qt)

    def post(self):
        post_id = int(self.request.get("id"))
        q = AllPost.get_by_id(post_id)
        q.votes += 1
        q.put()
        time.sleep(0.5)
        update = recent_posts(update=True) # for memcache
        posts = db.GqlQuery("SELECT * FROM AllPost ORDER BY created DESC LIMIT 10")
        posts = list(posts)
        self.render('latest.html', articles=posts)
  • 问题根源:刷新页面会再次发送 POST 请求,导致服务器再次更新数据库和重新渲染页面,从而触发浏览器的表单提交确认警报。

解决方案

为了解决这个问题,我们可以使用 AJAX 来实现投票功能。AJAX(Asynchronous JavaScript and XML)是一种在无需重新加载整个页面的情况下与服务器通信的技术。通过使用 AJAX,我们可以将投票请求发送到服务器,服务器更新数据库后立即返回结果,而无需重新渲染页面。

  • 解决方法:
<div class="article-votes">
  Votes: <span id="vote-count">{{ item.votes }}</span>
  <button id="vote-button">Vote+</button>
</div>
const voteButton = document.getElementById('vote-button');
voteButton.addEventListener('click', () => {
  const postId = {{ item.key().id() }};
  const voteCountElement = document.getElementById('vote-count');

  const request = new XMLHttpRequest();
  request.open('POST', '/vote');
  request.setRequestHeader('Content-Type', 'application/json');
  request.send(JSON.stringify({ postId }));

  request.onload = () => {
    if (request.status === 200) {
      const data = JSON.parse(request.responseText);
      voteCountElement.textContent = data.voteCount;
    } else {
      alert('Error voting for post.');
    }
  };
});
@app.route('/vote', methods=['POST'])
def vote():
    data = request.get_json()
    post_id = data['postId']

    post = AllPost.get_by_id(post_id)
    post.votes += 1
    post.put()

    return json.dumps({
        'voteCount': post.votes
    })

以上代码可以通过 AJAX 发送投票请求到服务器,服务器收到请求后更新数据库中的文章投票数,然后返回更新后的投票数,而无需重新渲染页面。这样就可以避免刷新页面时触发浏览器的表单提交确认警报。

代码例子

以上代码实现了使用 AJAX 来更新投票数的功能。用户点击投票按钮时,会触发一个 AJAX 请求,该请求将把投票数和帖子 ID 发送到服务器。服务器收到请求后,更新数据库中的投票数,然后以 JSON 格式返回更新后的投票数。客户端收到服务器的响应后,更新界面的投票数,无需重新渲染整个页面。