【问题标题】:Why AJAX call to Servlet (async) is executed multiple times?为什么多次执行对 Servlet(异步)的 AJAX 调用?
【发布时间】:2015-05-27 04:25:24
【问题描述】:

我正在使用 servlet 和 AJAX 做一个简单的登录应用程序。我很好奇为什么当我将 async 指定为 true 时会多次触发 AJAX 调用。当 async 被指定为 false 时,只调用一次。

示例:

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <title>Login</title>
</head>
<body>
    <form id="flogin" class="panel">
        <section class="panel-head">

        </section>
        <section class="panel-body">
            <input type="text" id="txt-username" class="textbox" placeholder="Usuario o email"/>
            <input type="password" id="txt-password" class="textbox" placeholder="Contraseña"/>
            <section class="form-action-group">
                <button type="submit" id="btn-login" class="btn btn-primary">Ingresar</button>
            </section>
        </section>
    </form>

    <script src="assets/js/login.js"></script>
</body>
</html>

JavaScript 源代码:

document.addEventListener("DOMContentLoaded", init, false);

function init() {
    var form = document.querySelector("#flogin");
    form.addEventListener("submit", handleLogin, true);

    function handleLogin(e) {
        e.preventDefault();
        var txtUsername = document.querySelector("#txt-username");
        var txtPassword = document.querySelector("#txt-password");

        var userdata = '{"username":'+txtUsername.value+',"password":'+txtPassword.value+'}';

        loginByAjax(userdata);
        resetForm(form);
    }

    function loginByAjax(data) {
        var message;
        var request = new XMLHttpRequest();
        request.open("POST", "LoginController", false);
        request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        request.onreadystatechange = function() {
            if(request.readyState != 4 || request.status != 200) {
                message = request.responseText;
            } else {
                message = request.responseText;
            }
            console.log(message);
        };
        request.send("userdata="+data);
    }

}

还有 servlet:

package com.company.controllers;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.company.utils.JsonUtils;

@WebServlet(asyncSupported=true, urlPatterns={"/LoginController"})
public class LoginController extends HttpServlet {
    private static final long serialVersionUID = 1L;
    private static final Logger logger = Logger.getLogger("LoginLogger");

    public LoginController() {
        super();
    }

    public void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter writer = response.getWriter();
        response.setContentType("text/plain");
        String strJson = request.getParameter("userdata");
        Map<String, Object> userData = JsonUtils.getMapFrom(strJson);
        String username = (String) userData.get("username");
        String password = (String) userData.get("password");

        if(username.equals("Duke") && password.equals("Duke777")) {
            writer.print("Usuario correctamente identificado");
        } else {
            writer.print("Usuario o contraseña incorrectas");
        }
        writer.flush();
        writer.close();
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
        try {
            processRequest(request, response);
        } catch(ServletException | IOException e) {
            logger.warning(e.getLocalizedMessage());
        }
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            processRequest(request, response);
        } catch(ServletException | IOException e) {
            logger.warning(e.getLocalizedMessage());
        }
    }

}

异步 ​​AJAX 调用图像:http://i.imgur.com/SbxUBsz.png

谁能解释一下为什么会这样?

【问题讨论】:

    标签: java javascript ajax servlets asynchronous


    【解决方案1】:

    确实是servlet没有被多次调用,发生的是当你进行异步调用时,onreadystatechange将在ajax请求阶段被调用多次,因为连接建立直到连接关闭,有4个ajax调用中的步骤,每个步骤都调用onreadystatechange,您可以通过request.readyState了解步骤:

    • 0:请求未初始化
    • 1:建立服务器连接
    • 2:收到请求
    • 3:处理请求
    • 4:请求完成,响应准备就绪

    您在每个步骤中都记录了消息,您可以通过这种方式在 ajax 调用结束时记录消息。

    request.onreadystatechange = function() {
       if(request.readyState == 4 && request.status == 200) {//if finish the ajax call and the status is ok
           message = request.responseText;
           console.log(message);
       };
       console.message('Checking the progress of the ajax call: ' + request.readyState);
    }
    

    您可以在 MDN XMLHttpRequest 中查看更多信息

    【讨论】:

    • 感谢您的回答。我非常感激。这:if(request.readyState == 4 || request.status == 200) 应该是:if(request.readyState == 4 &amp;&amp; request.status == 200) 最后回复。问候^^
    • 不客气,是的,完全正确,我更新了我的答案是复制和粘贴错误,谢谢指出。
    猜你喜欢
    • 1970-01-01
    • 2014-04-13
    • 2013-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多