为什么我第一次运行时此代码返回undefined



我想从上传的图像中获得一个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)
}