无法让 vanilla JS onreadystatechange 函数/readyState 4 工作

Posted

技术标签:

【中文标题】无法让 vanilla JS onreadystatechange 函数/readyState 4 工作【英文标题】:Cant get vanilla JS onreadystatechange function / readyState 4 to work 【发布时间】:2020-04-19 20:15:28 【问题描述】:

我正在为 HotSpot 创建一个“登录”页面。一旦用户输入他/她的电子邮件,他们就可以访问互联网。

为了完成这项工作,我使用了两个 AJAX 函数。

    点击提交后,用户名和密码被发送到路由器(授予用户互联网访问权限) 进行了第二次 AJAX 调用,这会将电子邮件保存到数据库中(在用户访问 Internet 之后(应该在他访问 Internet 之后,在他被重定向之前发送)。

目前,我无法获取...

xhr.onreadystatechange = function () var DONE = this.DONE || 4; if (xhr.readyState === XMLHttpRequest.DONE)

...函数工作。

Ajax 调用很早,用户会立即被重定向,并且电子邮件不会保存在数据库中(我认为这是因为它们是在用户访问互联网之前发送的)。

您能给我的任何帮助将不胜感激。

html 文档

<!DOCTYPE html>
<html>
<head>
<meta content="text/html" />
<meta charset="utf-8" />

<title>HotSpot</title>

</head>
<body>

    <!-- Email Form, which gets saved into the DB -->
    <form accept-charset="utf-8" name="mail" onsubmit="return false;" method="post" id="mail">
        <h1>Hotspot</h1>
        <h2>To gain internet access, enter your email.</h2>
        <br />
        <input type="text" id="email" name="email" autofocus="autofocus" />
        <br />
        <input type="submit" value="Submit" id="submit_ok" name="submit_ok" /> <br />
    </form>

<script type="text/javascript">

document.getElementById("submit_ok").addEventListener("click", SendAjax);
function SendAjax() 
    var email = document.getElementById("email").value;
    console.log(email);
    // Check if fields are empty 
    if (email=="") 
        alert("Please enter your email.");
    
    // AJAX code to submit form
    else
        var xhr = new XMLHttpRequest();
        xhr.open('POST', 'http://router/login', true);
        xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded", "Access-Control-Allow-Origin: *");
        xhr.send("popup=true&username=HSuser&password=SimpleUserPassword");

        xhr.onreadystatechange = function () 
            var DONE = this.DONE || 4;
            if (xhr.readyState === XMLHttpRequest.DONE)
                var xhr2 = new XMLHttpRequest();
                xhr2.open('POST', 'http://server/insertDB.php', true);
                xhr2.setRequestHeader("Content-type", "application/x-www-form-urlencoded", "Access-Control-Allow-Origin: *");
                var useremail = document.getElementById("email").value;
                xhr2.send("Email="+encodeURIComponent(useremail));

                xhr2.onreadystatechange = function () 
                var DONE = this.DONE || 4;
                    if (xhr2.readyState === XMLHttpRequest.DONE) 
                        location.href = "http://server/redirected.html";
                    
                ;
            
        
    

这个也试过了,还是不行。

            var xhr = new XMLHttpRequest();
            xhr.open('POST', 'http://router/login', true);
            xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded", "Access-Control-Allow-Origin: *");
            xhr.send("popup=true&username=HSuser&password=SimpleUserPassword");
            xhr.onreadystatechange = function () 
            var DONE = this.DONE || 4;
                  if (this.readyState === DONE)
                    etc etc
                  

PHP 文档(我认为这对本例来说并不重要,但你知道……以防万一)

<?php

    require ('connect.php');

    $clean_email = "";
    $cleaner_email = "";


    if(isset($_POST['email']) && !empty($_POST['email']))
        //sanitize with filter
        $clean_email = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);
        //sanitize with test_input
        $cleaner_email = test_input($clean_email);
        //validate with filter
        if (filter_var($cleaner_email,FILTER_VALIDATE_EMAIL))
            // email is valid and ready for use
            echo "Email is valid";  
            //Email is a row inside the database
            $stmt = $DB->prepare("INSERT INTO addresses (Email) VALUES (?)");
            $stmt->bind_param("s", $cleaner_email);
            $stmt->execute();
            $stmt->close();
         else 
            // email is invalid and should be rejected
            echo "Invalid email, try again";
         
     else 
    echo "Please enter an email";
    

    function test_input($data) 
      $data = trim($data);
      $data = stripslashes($data);
      $data = htmlspecialchars($data);
      return $data;
    

    $DB->close();   
?>

编辑:

粘贴一个sn-p的代码,已经改变了。

        else
            var xhr = new XMLHttpRequest();
            xhr.open('POST', 'http://router.login', true);
            xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded", "Access-Control-Allow-Origin: *");
            xhr.send("popup=true&username=HSuser&password=SimpleUserPassword");

            var xhr2= new XMLHttpRequest();

            var useremail = document.getElementById("email").value;
            xhr.onreadystatechange = function () 
            console.log(DONE);
            var DONE = this.DONE || 4;
                if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) 
                    console.log(DONE);              
                    console.log(xhr.status);
                    xhr2.open('POST', 'http://server.insertDB.php', true);
                    xhr2.setRequestHeader("Content-type", "application/x-www-form-urlencoded", "Access-Control-Allow-Origin: *");
                    xhr2.send("Email="+encodeURIComponent(useremail));                  
                
            
            xhr2.send("Email="+encodeURIComponent(useremail));  
        
    

我需要将 email 变量移到外面,否则我会收到未定义的错误。

我现在在xhr2.send 上遇到错误...

未捕获的 DOMException:无法在“XMLHttpRequest”上执行“发送”:对象的状态必须是 OPENED。在 HTMLInputElement.SendAjax

【问题讨论】:

在事件处理程序中,比如onreadystatechangethis 可能不是你,而是xhr。使用日志记录检查它,如果是这种情况,请将“您的”this 保存到闭包中的变量中(或者如果您真的想要,也可以将其添加到 xhr)。 公平地说,这句话对我来说没有多大意义。我对this 语句以及它们给我带来的麻烦并不是那么有经验。我将如何记录这个?控制台日志(完成);我假设?这个函数的文档可以在这里找到 --> en.wikipedia.org/wiki/… 做了 console.log(DONE);它确实得到了 4。我用调试器完成了它,发送第一个 AJAX 花了大约 5 秒。 【参考方案1】:

您必须在发送请求之前设置您的侦听器。这里是一个使用 onload 监听器的例子

    // Set up our HTTP request
    var xhr = new XMLHttpRequest();

    // Setup our listener to process completed requests
    xhr.onload = function () 

        // Process our return data
        if (xhr.status >= 200 && xhr.status < 300) 
            // What do when the request is successful
            console.log('success!', xhr);
         else 
            // What do when the request fails
            console.log('The request failed!');
        

        // Code that should run regardless of the request status
        console.log('This always runs...');
    ;

    // Create and send a GET request
    // The first argument is the post type (GET, POST, PUT, DELETE, etc.)
    // The second argument is the endpoint URL
    xhr.open('GET', 'https://jsonplaceholder.typicode.com/posts');
    xhr.send();

这里是一个准备状态变化监听器的例子

    xhr.open(method, url, true);
    xhr.onreadystatechange = function () 
        if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) 
            console.log(xhr.responseText);
        
    ;
    xhr.send();

这是您的代码,调用顺序正确

function SendAjax() 
    var email = document.getElementById("email").value;
    console.log(email);
    // Check if fields are empty 
    if (email=="") 
        alert("Please enter your email.");
    
    // AJAX code to submit form
    else
        var xhr = new XMLHttpRequest();
        xhr.open('POST', 'http://router/login', true);
        xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded", "Access-Control-Allow-Origin: *");

        xhr.onreadystatechange = function () 
            var DONE = this.DONE || 4;
            if (xhr.readyState === XMLHttpRequest.DONE)
                var xhr2 = new XMLHttpRequest();
                xhr2.open('POST', 'http://server/insertDB.php', true);
                xhr2.setRequestHeader("Content-type", "application/x-www-form-urlencoded", "Access-Control-Allow-Origin: *");
                var useremail = document.getElementById("email").value;

                xhr2.onreadystatechange = function () 
                    var DONE = this.DONE || 4;
                    if (xhr2.readyState === XMLHttpRequest.DONE) 
                        location.href = "http://server/redirected.html";
                    
                ;
                xhr2.send("Email="+encodeURIComponent(useremail));
            
        

        xhr.send("popup=true&username=HSuser&password=SimpleUserPassword");
    

【讨论】:

好吧,我没有请求任何东西,所以我不知道为什么我需要 onload 函数,尤其是如果我的 xhr 请求超出了函数的范围... 当然你在请求一个 POST 请求“XMLHttpRequestEventTarget.onload 是当一个 XMLHttpRequest 事务成功完成时调用的函数。” onload 监听器不是这里的重点,重点是您必须在发送请求之前设置监听器。我已经添加了另一个示例 感谢您的澄清。我会试一试,然后告诉你会发生什么。 等等。现在我更加困惑了。当我们甚至还没有设置 xhr 时(因为它在括号之外),怎么能完成 xhr.readyState。

以上是关于无法让 vanilla JS onreadystatechange 函数/readyState 4 工作的主要内容,如果未能解决你的问题,请参考以下文章

将 jQuery each() 循环重新设计为 Vanilla JS

node.js 的新手;需要帮助将 npm 模块导入我的前端 vanilla JS 项目

混合 Angular 1.x + Angular 6 应用程序,在 Angular 1.x 中包含 vanilla JS 和 TS 文件

将“Vanilla”Javascript 库加载到 Node.js 中

javascript AJAX与Vanilla JS

javascript JQuery到Vanilla js指南