FileReader:reader.result 显然不是时为空

FileReader: reader.result is null when it clearly isnt

我已经尝试让我的代码工作几个小时了,我对此感到非常恼火和厌倦,想寻求一些帮助。

我正在尝试为文件输入类型做一个简单的 API(不要开始说我的代码不好,我只是想要一些有用的东西,并想寻求你的帮助。谢谢你.

我知道 onload 是异步的,我已经尝试了我能想到的所有可能的方法,这让我很恼火。我稍后会回来查看是否有人可以提供帮助。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>File Input - Testing</title>
    <script src="js/app_2.js" defer></script>
</head>
<body>
    <input type="file" id="file_input" />
    <img id="image_preview" />
</body>
</html>
let file_input;
document.addEventListener("DOMContentLoaded", function() {
    file_input = document.querySelector("#file_input");
    file_input.addEventListener("change", () => on_file_update());
});

function FileInputManager(files) {
    if (!files || typeof files !== "object")
        return console.error("FileInputManager: Missing file_input_element.files, please provide it so I can run!");

    let reader = new FileReader();
    let file = files[0];
    let types = file.type.split("/");
    let full_type = types[0] === "" ? "empty" : types.join("/");

    if (!file)
        return console.error("FileInputManager: No file selected, maybe something went wrong?");

    // Determine How To Read The File By Testing The Mime-Type
    this.determine_read_type = function() {
        switch (types[0]) {
            case "image":
                return reader.readAsDataURL(file);
            case "text":
                return reader.readAsText(file);
            case "application":
                return reader.readAsText(file);
            default:
                console.warn(`FileInputManager: File reading has been aborted, file type [type: ${full_type}] unsupported.`);
                break;
        }
    }

    this.determine_read_type();

    let result = "unknown";
    reader.onload = function() {
        result = reader.result;
    };

    // switch(types[1]) {
    //     case "octet-stream":
    //         return console.error(`FileInputManager: Unable to run, file type [type: ${full_type}] not allowed.`);


    this.getResult = function() {
        return result;
    }

    this.getMimeType = function() {
        if (types.length <= 0)
            return console.error("FileInputManager: Mime-Type is missing, maybe something went wrong?");
        return String(types.join("/"));
    }

    return;
}

function on_file_update() {
    let reader_file = new FileInputManager(file_input.files);
    console.log(reader_file.getResult());
    if (reader_file.getMimeType().startsWith("image"))
        document.querySelector("#image_preview").src = reader_file.getResult();

    if (reader_file.getMimeType().startsWith("text"))
        console.log(reader_file.getResult());
}

您在结果可用之前致电 getResult。正如您所说,读取过程是异步的,但您的代码并不等待读取完成。您 启动 FileInputManager 中的进程,但随后 on_file_update 立即调用 getResult,它仍然是 "unkonwn",因为没有分配给它因为你分配了 "unknown".

您必须等待 onload 回调才能使用结果。 FileInputManager 将需要提供某种方式来连接它获得的回调——让您提供自己的回调、返回承诺,诸如此类。

正如您正确指出 onLoad 是异步的,但您仍然尝试在下面的行 new FileInputManager(file_input.files); 中调用 new FileInputManager(file_input.files); 后立即访问结果

let reader_file = new FileInputManager(file_input.files);
console.log(reader_file.getResult());

您需要 return 来自 FileInputManager 的 getResult 的承诺并等待它

function FileInputManager(files) {
    let callbackRes = () => {};
    const promise = new Promise((res, rej ) => {
        this.callbackRes = res;
    });

    if (!files || typeof files !== "object")
        return console.error("FileInputManager: Missing file_input_element.files, please provide it so I can run!");

    let reader = new FileReader();
    let file = files[0];
    let types = file.type.split("/");
    let full_type = types[0] === "" ? "empty" : types.join("/");

    if (!file)
        return console.error("FileInputManager: No file selected, maybe something went wrong?");

    // Determine How To Read The File By Testing The Mime-Type
    this.determine_read_type = function() {
        switch (types[0]) {
            case "image":
                return reader.readAsDataURL(file);
            case "text":
                return reader.readAsText(file);
            case "application":
                return reader.readAsText(file);
            default:
                console.warn(`FileInputManager: File reading has been aborted, file type [type: ${full_type}] unsupported.`);
                break;
        }
    }

    this.determine_read_type();

    let result = "unknown";
    reader.onload = function() {
        callbackRes(reader.result);
    };

    // switch(types[1]) {
    //     case "octet-stream":
    //         return console.error(`FileInputManager: Unable to run, file type [type: ${full_type}] not allowed.`);


    this.getResult = function() {
        return promise;
    }

    this.getMimeType = function() {
        if (types.length <= 0)
            return console.error("FileInputManager: Mime-Type is missing, maybe something went wrong?");
        return String(types.join("/"));
    }

    return;
}

async function on_file_update() {
    let reader_file = new FileInputManager(file_input.files);
    const res = await reader_file.getResult();
    console.log(res);
    if (reader_file.getMimeType().startsWith("image"))
        document.querySelector("#image_preview").src = reader_file.getResult();

    if (reader_file.getMimeType().startsWith("text"))
        console.log(res);
}