为什么这个代码 returns 在我第一次 运行 时未定义

why this code returns undefined when I first run

我想从上传的图片中获取 base64 字符串。第一次当我 运行 代码时,它 returns 未定义。当我 运行 之后它工作正常。我该如何解决这个问题?

<!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>

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 运行s 异步所以 reader.onload 不会立即完成。你 return resultreader.onload 完成之前 result 没有价值。

第二次 运行 upload,结果确实有值,因为 reader.onload 已经完成。记录的结果很可能是之前调用 upload.

的结果

您可以通过使 upload 成为等待来自 getBase64 的响应的异步函数来解决此问题。这还需要您在 reader.onload 中生成结果,而不是在 <script> 标签

中全局设置值

答案 ASDFGerte linked 确实解释了这一点,但我会根据您的问题进行解释。

让我们看看会发生什么:

用户点击按钮

函数上传执行

getBase64 被调用

创建文件reader并读取文件

.onload 事件侦听器分配一个函数

.onerror 事件侦听器分配一个函数

return变量结果,此时不存在,因为.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>

您需要在 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)
}