首页 > 解决方案 > Ajax 请求保持在 readyState=1

问题描述

正如标题所说,我试图在这个 HTML 中使用 ajax,并在 php 文件的选择列表中接收所选车辆以将其插入数据库。在此之后,如果插入正确,则假设 php 会发回与新插入关联的 id(autoincrement) 并将其显示在 HTML 上。问题是 ajax 连接在 readyState=1 处停止(就在打开通信之后)并且控制台日志中没有显示错误。

    <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<select name="type" id="type">
    <option value="Coche">Car</option>
    <option value="Motocicleta">Cicle</option>
    <option value="Barco">Ship</option>
</select>

    <button id="btn_search">Search</button>

    <div class="List" id="List">

    </div>

<script type="text/javascript">
    var xhreq=new XMLHttpRequest();
    var btn_search=document.getElementById("btn_search");
    var type=document.getElementById("type");
    btn_search.addEventListener("click",find_veh);

    function find_veh(event){
        console.log("Find_veh1-> onreadystate:"+xhreq.readyState);
        xhreq.open("GET","Ej1.php?q="+type.value,true);
        console.log("Find_veh2-> onreadystate:"+ xhreq.readyState);
        xhreq.onreadystatechange= show_veh;
        xhreq.send(null);
        console.log("Find_veh3-> onreadystate:"+ xhreq.readyState);
    }


    function show_veh(){
        if((xhreq.readyState==4) && (xhreq.status==200)){
            console.log("Show_veh correct")
            document.getElementById("show_vehi").innerText=xhreq.responseText;
        }else {
            console.log("Error in show_veh");
        }
    }

</script>

</body>
</html>

PHP

     <?php
    $dbConn = new mysqli("192.168.1.62", "root", "pass", "AJAX");

if ($dbConn->connect_error) {
} else {
    if (isset($_GET["q"])) {
        $q = $_GET["q"];

        $query = 'SELECT id FROM Vehiculos WHERE tipo='.$q.";";
        $result = $dbConn->query($query);
        $listHTML .= "<ul>";
        while($idVehi = $result->fetch_assoc()){
            $listHTML .="<li>".$idVehi["id"]."</li>";
        }
        $listHTML .="</ul>";

      echo $listHTML;
    }
}

标签: javascriptphpajax

解决方案


上面的代码似乎缺少带有 ID 的 HTML 元素,show_vehiajax 回调使用它来显示结果。与您打开 XMLHttpRequest 对象然后执行实际请求的方式相比,这种方式似乎很奇怪——我通常希望 XMLHttpRequest 在发出请求时打开,而不是在页面加载时打开。

从本质上讲,你的 ajax 似乎没有任何本质上的错误~它可以工作,所以也许是对 XHR 请求的各个阶段的误解,导致了对readyState保持在 1 的担忧。

以下对您的原始 javascript 进行了一些细微修改,以指示您可能没有注意到的信息(回调错误并不是真正的错误),并且因为测试页面被称为ej1.phpajax 请求,所以这里通过发送一些在同一页面上处理随机文本作为回复而不是实际的数据库查询。

<?php

    if( !empty( $_GET['q'] ) ){
        exit('Some sort of response for the ajax callback to process...'.date(DATE_ATOM));
    }

?>
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <select name="type" id="type">
            <option value="Coche">Car</option>
            <option value="Motocicleta">Cicle</option>
            <option value="Barco">Ship</option>
        </select>
        <button id="btn_search">Search</button>
        <button id="btn_search_alternative">Search (Alternative)</button>
        <div class="List" id="List"></div>
        <div id='show_vehi'></div>

        <script>
            var css={
                red:'color:red',
                green:'color:green',
                blue:'color:blue'
            }



            function ajax( url, type, callback ){
                var xhr=new XMLHttpRequest();
                    xhr.onreadystatechange=function(){
                        if( this.status==200 && this.readyState==4 ){
                            console.info( '%cAfter Response: %s', css.green, xhr.readyState );
                            callback( this.response );
                        }
                    };
                    console.info( '%cBefore Open: %s', css.red, xhr.readyState );
                    xhr.open('GET', url+'?q='+type,true );
                    console.info( '%cBefore Send: %s', css.blue, xhr.readyState );
                    xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
                    xhr.send( null );
            }

            document.getElementById('btn_search_alternative').addEventListener('click',function(e){
                function callback(r){
                    document.getElementById('show_vehi').textContent=r;
                }
                ajax( 'ej1.php', document.getElementById('type').value, callback );
            });





            /* slightly modified original */
            var xhreq=new XMLHttpRequest();
            console.info('After Initialisation: %d',xhreq.readyState)


            var btn_search=document.getElementById("btn_search");
            var type=document.getElementById("type");
            btn_search.addEventListener("click",find_veh);



            function find_veh(event){
                console.log("Before Open: Find_veh1-> onreadystate:"+xhreq.readyState);
                xhreq.open("GET","Ej1.php?q="+type.value,true);
                console.log("After Open, Before Change: Find_veh2-> onreadystate:"+ xhreq.readyState);
                xhreq.onreadystatechange= show_veh;
                xhreq.send(null);
                console.log("After Send: Find_veh3-> onreadystate:"+ xhreq.readyState);
            }


            function show_veh(){
                if((xhreq.readyState==4) && (xhreq.status==200)){
                    console.log("Response received: Show_veh correct")
                    document.getElementById("show_vehi").innerText=xhreq.responseText;
                }else {
                    console.log("Error in show_veh: readyState=%d status=%d",xhreq.readyState,xhreq.status);
                }
            }

        </script>
    </body>
</html>

但是 - 真正的问题在于您的 PHP 代码。SQL 语句完全容易受到 SQL 注入的攻击,因此我建议学习如何实现Prepared Statements- 我很感激由于数据库主机的 C 类 IP 地址,目前这不是实时的,但现在是进行更改的时候了。

你可以尝试这样的事情(未经测试)

<?php

    if( !empty( $_GET['q'] ) ){

        $html=array();


        $dbConn = new mysqli("192.168.1.62", "root", "pass", "AJAX");
        $sql='select `id` from `vehiculos` where tipo=?';
        $stmt=$dbConn->prepare( $sql );

        $q=filter_input( INPUT_GET, 'q', FILTER_SANITIZE_STRING );

        if( $stmt ){
            $stmt->bind_param('s', $q );
            $res=$stmt->execute();

            if( $res ){
                $stmt->store_result();
                $stmt->bind_result( $id );
                $html[]='<ul>';
                while( $stmt->fetch() )$html[]=sprintf( '<li>%s</li>',$id );
                $html[]='</ul>';
            }
        }

        exit( implode( PHP_EOL, $html ) );
    }
?>

推荐阅读