reactjs - ReactJS - axios.post 的同步问题
问题描述
我在 reactjs 中的 axios.post 调用存在同步问题。我有一个输入区域供用户选择要提交到 axios.post 的本地文件,该文件被翻译成数组缓冲区,然后通过 axios 调用发送到 microsoft faces api。如果我选择一个图像,然后按分析按钮,同步将关闭,它会尝试在没有数组缓冲区的情况下发出发布请求。如果我第二次单击它,它会正确发布帖子。
我对等待和异步还很陌生,对我的问题的任何输入都会有很大的帮助。我考虑过使用布尔标志,但想了解如何使用正确的设计来改进此功能。
import React, { useState } from "react";
import axios from "axios";
import { Button, Container, Row, Col } from "react-bootstrap";
import "../../styling/FacialRecognition.css";
import defaultImage from "../../assets/images/defaultImage.png";
function FacialRecognition() {
const [image, setImage] = useState("");
const [imageData, setImageData] = useState([]);
const [responseData, setResponseData] = useState([]);
const [dataLoad, setDataLoad] = useState(false);
//translates the local file to the array buffer, and sets the imageData.
function TranslateImageToArrayBuffer(imageToTranslate) {
let reader = new FileReader();
reader.readAsArrayBuffer(imageToTranslate);
reader.onloadend = () => {
setImageData(reader.result);
};
}
//Makes the call with the url,options, and the arraybuffer.
function ProcessImage(localImage) {
TranslateImageArrayBuffer(localImage);
console.log("ImageData: " + imageData);
var subscriptionKey = "<subscriptionkey>";
var uriBase =
"https://(urlgoeshere).cognitiveservices.azure.com/face/v1.0/detect";
const options = [
"returnFaceId=true",
"returnFaceLandmarks=true",
"returnFaceAttributes=age,gender,headPose,smile,facialHair,glasses,emotion,hair,makeup,accessories",
];
uriBase = uriBase.concat("?", options.join("&"));
// Perform the REST API call.
axios
.post(uriBase, imageData, {
headers: {
"Content-Type": "application/octet-stream",
"Ocp-Apim-Subscription-Key": subscriptionKey,
},
})
.then(function (response) {
// Display the image.
var blob = new Blob([imageData]);
var url = URL.createObjectURL(blob);
setDataLoad(true);
document.querySelector("#sourceImage").src = url;
console.log("Status text: " + response.status);
console.log("Status text: " + response.statusText);
console.log(response.data);
setResponseData(response.data);
})
.catch(function (error) {
console.log(error);
});
}
let value = responseData.map((e) => JSON.stringify(e, null, 2));
return (
<div>
<Container fluid="xl">
<Row>
<Col xs="auto">
<p>
Select a local image, and then click the <b>Analyze face button.</b>
</p>
</Col>
</Row>
<Row>
<Col x="auto">
<label>Image to analyze: </label>
<input
type="file"
name="inputImage"
id="inputImage"
autoComplete="off"
accept="image/png, image/jpeg"
onChange={(e) => setImage(e.target.files[0])}
style={{ width: "60%", marginLeft: "1vw" }}
/>
<Button
variant="info"
onClick={() => ProcessImage(image)}>
Analyze face
</Button>
</Col>
</Row>
<Row style={{ marginTop: "2vw" }}>
<Col xs="6">
<label>
<strong>Response</strong>
</label>
</Col>
<Col xs="auto">
<label>
<strong>Source Image</strong>
</label>
</Col>
</Row>
<Row>
<Col>
{dataLoad ? (
<textarea
id="responseTextArea"
className="UIInput"
style={{ width: "100%", height: "429px" }}
value={value}
readOnly={true}
disabled="disabled"></textarea>
) : (
<textarea
id="responseTextArea"
className="UIInput"
style={
dataLoad
? { display: "none" }
: { width: "100%", height: "auto" }
}
defaultValue="This field will display analyzed data on the image"
readOnly={true}
disabled="disabled"></textarea>
)}
</Col>
<Col xs="6">
{dataLoad ? (
<img
id="sourceImage"
alt=""
style={
dataLoad
? { width: "80%" }
: { display: "none" }
}
/>
) : (
<img
id="defaultImage"
src={defaultImage}
alt=""
style={
dataLoad
? { display: "none" }
: { width: "80%" }
}
/>
)}
</Col>
</Row>
</Container>
</div>
);
}
export default FacialRecognition;
我也尝试设置TranslateImageToArrayBuffer
为异步函数,并将 axios 调用放入 a 中.then(response => {axios.post...})
,但没有运气。
编辑:我还尝试将我的翻译功能内容包装在一个承诺中。
async function TranslateImageToArrayBuffer(imageToTranslate) {
return new Promise((resolve, reject) => {
var reader = new FileReader();
reader.onload = () => {
setImageData(reader.result);
resolve(imageData);
};
reader.onerror = () => {
reject(reader.result);
};
reader.readAsArrayBuffer(imageToTranslate);
});
}
并在我的 ProcessImage 函数中使用const contents = await TranslateImageToArrayBuffer(localImage);
一行来等待该值。仍然有同步问题。
解决方案
我无法让它与异步一起工作,所以我将我的函数 onChange 用于输入文件以将图像转换为数组缓冲区,而不是在ProcessImage()
.
<input
type="file"
name="inputImage"
id="inputImage"
autoComplete="off"
accept="image/png, image/jpeg"
onChange={(e) =>{ TranslateImageToArrayBuffer(e.target.files[0]);setImage(e.target.files[0]) }}
style={{ width: "60%", marginLeft: "1vw" }}
/>
<Button
variant="info"
onClick={() => ProcessImage()}>
Analyze face
</Button>
这绕过了进行异步设置的需要。
推荐阅读
- java - 匹配字符串中的 + 运算符,除非它在引号中?
- css - 在 html 和 css 中缩放叠加图像时出现奇怪的像素偏移
- android - 如何在android中以编程方式更改片段的主题
- javascript - 向下滚动时标题在晃动
- r - 反应性数据,转换和覆盖
- apache-kafka - 卡夫卡主要演员
- thymeleaf - Thymeleaf 更新链接
- ionic3 - 如何使用 ionic v3 警报对话框覆盖 mfp 8.0 的默认直接更新弹出窗口
- django - 使用MultiTableMixin时如何识别每张表
- microsoft-cognitive - HoloLens 上的自定义视觉