我正在 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 函数中抛出的错误是否不会一直返回到调用函数?抛出错误时我是否需要做一些不同的事情,以便它会返回给调用者?当错误再次出现时,我是否没有正确捕获错误?
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"
};