You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

XMLHttpRequest同步请求返回值异常及TypeError错误排查求助

问题解决:XHR函数无法返回值及null读取length错误

问题根源

  1. 同步XHR事件执行顺序偏差:你使用了同步XHR,但onreadystatechange事件的触发时机滞后于items = products.length的执行,此时products仍为初始值null,直接读取length就会抛出Cannot read properties of null (reading 'length')错误。
  2. SQL注入风险:PHP代码直接拼接用户输入到SQL语句中,存在严重安全漏洞。

修复方案

方案1:修正同步XHR逻辑(不推荐,易阻塞页面)

同步请求完成后,可直接读取XHR响应,无需依赖onreadystatechange事件:

function fetch_api_products(query) {
    var xhr = new XMLHttpRequest();
    var url = 'products.php?act=search_products&query=' + encodeURI(query);
    xhr.open('GET', url , false);
    xhr.send();
    
    if (xhr.status === 200) {
        var products = xhr.responseText;
        items = products.length;
        return products;
    } else {
        items = 0;
        return null;
    }
}

方案2:改用异步XHR+Promise(推荐,无页面阻塞)

同步XHR会阻塞浏览器主线程,异步方式更友好:

function fetch_api_products(query) {
    return new Promise((resolve, reject) => {
        var xhr = new XMLHttpRequest();
        // 单独编码query参数更严谨
        var url = `products.php?act=search_products&query=${encodeURIComponent(query)}`;
        xhr.open('GET', url , true);
        
        xhr.onload = () => {
            xhr.status === 200 ? resolve(xhr.responseText) : reject(new Error(`请求失败:${xhr.status}`));
        };
        xhr.onerror = () => reject(new Error('网络请求出错'));
        
        xhr.send();
    });
}

// 调用示例
fetch_api_products('你的查询关键词')
    .then(products => {
        // 建议转成JSON对象处理,而非直接用字符串长度
        const productList = JSON.parse(products);
        items = productList.length;
        alert(JSON.stringify(productList));
        // 后续业务逻辑写在这里
    })
    .catch(err => {
        console.error(err);
        items = 0;
    });

修复PHP的SQL注入漏洞

使用PDO预处理语句,彻底避免注入风险:

$dbh = new PDO(
    'mysql:host=' . $config['db_server'] . ';dbname=' . $config['db_name'],
    $config['db_user'],
    $config['db_password']
);
$dbh->exec("set names utf8mb4");

if(isset($_GET['query'])){
    $query = $_GET['query'];
    // 预处理语句+占位符
    $stmt = $dbh->prepare("SELECT id,name,barcode,price FROM products WHERE name LIKE ? OR barcode LIKE ?");
    $likePattern = '%' . $query . '%';
    // 绑定参数,指定类型
    $stmt->bindParam(1, $likePattern, PDO::PARAM_STR);
    $stmt->bindParam(2, $likePattern, PDO::PARAM_STR);
    $stmt->execute();
    
    echo json_encode($stmt->fetchAll(PDO::FETCH_ASSOC));
}

额外提示

  • 拿到响应后,记得用JSON.parse()将字符串转为JSON对象,这样productList.length才是实际的商品数量,而非响应字符串的长度。
  • 尽量减少全局变量(比如items)的使用,可将数据封装在函数或回调内部,降低代码耦合度。

内容的提问来源于stack exchange,提问作者Hakeem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 00:57:36