如何使用调用者函数捕获 XMLHttpRequest 调用中的错误

问题描述 投票:0回答:1

我正在 ReactJS 中构建一个功能,允许用户将文件上传到照片应用程序。我的后端验证文件以确保它们属于受支持的类型,而不是某种随机类型,如 .txt 或 .bat 或其他非图像文件类型。如果用户尝试上传不支持的类型,服务器将响应 HTTP 415 错误“不支持的媒体类型”。我可以在发送此请求的函数中访问此状态代码,如下所示:

export function sendCSRFRequest(formData, targetURL) {  
    const request = new XMLHttpRequest();

    // check for HTTP response status
    request.onreadystatechange = () => {
        if (request.readyState === 4) {
            if (request.status === 200) {
                console.log("Upload successful!");
            } else if (request.status === 415) {
                throw new Error("Can't upload that!");
            }
        }
    };

    request.open('POST', targetURL);
    request.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
    request.send(formData);
};

此代码成功识别 415 错误,并将错误抛出到控制台,并显示文本“无法上传!”但我想要做的是将这个错误返回给调用函数,这样我就可以进行一些条件渲染并向用户显示一个警报,告诉他们直接在 UI 中出了什么问题。这是调用函数:

async function handleUpload(e, files, setFiles, setUploadFailed) {
    e.preventDefault() // do not redirect page
    const formData = new FormData();
    files.forEach(file => {formData.append('file', file)});
    try {
        sendCSRFRequest(formData, 'api/upload/'); // Function shown above
    } catch (e) {
        console.log("Found an error!");
        console.error(e);
        setUploadFailed(true); // Triggers an alert in the UI
    }
    
    await setFiles([]); // If upload is successful, clear out state "files"
};

第二个函数似乎没有捕获我在第一个函数中抛出的错误,我不明白为什么。我尝试以各种方式设置我的 try/catch 块,在不同的行上添加和删除“await”,更改为

sendCSRFRequest().catch(e => /* do something */)
,我尝试的任何方法似乎都不起作用。由于某种原因,sendCSRFRequest 函数中抛出的错误是否不会一直返回到调用函数?抛出错误时我是否需要做一些不同的事情,以便它会返回给调用者?当错误再次出现时,我是否没有正确捕获错误?

javascript error-handling try-catch
1个回答
0
投票

参见 readystatechange 事件

onreadystatechange 事件不是同步的。
它不会等待sendCSRFRequest的响应并继续执行。

你可以尝试使用Promisified方法。

export function sendCSRFRequest(formData, targetURL) {
    return new Promise((resolve, reject) => {
        const request = new XMLHttpRequest();

        // check for HTTP response status
        request.onreadystatechange = () => {
            if (request.readyState === 4) {
                if (request.status === 200) {
                    console.log("Upload successful!");
                    resolve();
                } else if (request.status === 415) {
                    reject("Can't upload that!");
                }
            }
            resolve();
        };

        request.open('POST', targetURL);
        request.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
        request.send(formData);
    });
}

并用await调用它。

async function handleUpload(e, files, setFiles, setUploadFailed) {
    e.preventDefault() // do not redirect page
    const formData = new FormData();
    files.forEach(file => {formData.append('file', file)});
    try {
        await sendCSRFRequest(formData, 'api/upload/'); // Function shown above
    } catch (e) {
        console.log("Found an error!");
        console.error(e);
        setUploadFailed(true); // Triggers an alert in the UI
    }
    
    await setFiles([]); // If upload is successful, clear out state "files"
};
© www.soinside.com 2019 - 2024. All rights reserved.