我想从上传的图像中获得一个base64字符串。当我第一次运行代码时,它返回undefined。当我追着跑的时候,效果很好。我该怎么解决这个问题?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Upload</title>
</head>
<body>
<input type="file" id="file">
<button id="button" onclick="upload()">Upload</button>
<script type="text/javascript">
var result;
function getBase64(file) {
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function () {
result = reader.result;
};
reader.onerror = function (error) {
console.log('Error: ', error);
};
return result;
}
function upload() {
var file = document.querySelector('input').files[0];
console.log(getBase64(file));
}
</script>
</body>
</html>
链接的答案确实解释了这一点,但我将在您的问题中进行解释。
让我们来看看会发生什么:
用户点击按钮
功能上传执行
getBase64被称为
创建一个文件读取器并读取文件
为.onload
事件侦听器分配一个函数
为.onerror
事件侦听器分配一个函数
返回变量result,此时该结果不存在,因为.onload
事件尚未触发。
第二次单击后,事件已触发,但对于以前的结果,而不是新的结果。
第二个目标是解决这个问题,我最喜欢的方法是使用async await
语法。
检查一下你的代码的返工
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Upload</title>
</head>
<body>
<input type="file" id="file">
<button id="button" onclick="upload()">Upload</button>
<script type="text/javascript">
async function getBase64(file) {
var reader = new FileReader();
reader.readAsDataURL(file);
let result;
await new Promise(resolve => {
reader.onload = function () {
result = reader.result;
resolve();
};
reader.onerror = function (error) {
console.log('Error: ', error);
resolve();
};
});
return result;
}
async function upload() {
var file = document.querySelector('input').files[0];
const result = await getBase64(file);
console.log(result);
}
</script>
</body>
</html>
function getBase64(file) {
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function () {
return reader.result;
};
reader.onerror = function (error) {
console.log('Error: ', error);
};
}
async function upload() {
var file = document.querySelector('input').files[0];
let result = await getBase64(file)
console.log(result);
}
FileReader
异步运行,因此reader.onload
不会立即完成。在reader.onload
完成之前返回result
,因此result
没有值。
第二次运行upload
时,结果确实有一个值,因为reader.onload
已经完成。记录的结果很可能是上一次调用upload
的结果。
您可以通过将upload
设置为等待getBase64
响应的异步函数来解决此问题。这也需要您在reader.onload
中生成结果,而不是在<script>
标签中全局设置值
您需要在upload()
之外声明FileReader
,并对console.log
使用onload
函数。
var reader = new FileReader();
reader.onload = function (event) {
var dataURL = event.target.result;
console.log(dataURL);
};
在update
函数中仅使用readDataURL
function upload() {
var file = document.querySelector("input").files[0];
reader.readAsDataURL(file)
}