You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

await未完成时then提前执行:表单文件转Base64后AJAX请求异常

问题分析与解决方案

核心问题

  1. loopChildren异步等待失效:$(children).each的回调是异步函数,但each方法本身不会等待这些异步操作完成,导致resolve(allData)在文件等异步内容处理完成前就执行,传给AJAX的allData不完整。
  2. getContent多文件逻辑错误:遍历文件时第一个文件处理完就直接resolve,后续文件未处理,也无法返回多文件的Base64数组。
  3. 冗余Promise嵌套:部分函数混用async/await和.then,逻辑混乱易出错。

修改后的完整代码

$(document).ready(function () {
    $("form").submit(async function (e) {
        e.preventDefault();

        const children = $(this).find("input, textarea");
        console.log(children.length);

        const nodeId = $(this).attr("data-nodeId");

        // 简化流程:先获取完整数据再调用AJAX
        const allData = await loopChildren(children);
        ajaxCall(allData, nodeId);
    })
});

// 重构loopChildren:用Promise.all等待所有异步操作完成
function loopChildren(children) {
    // 遍历表单元素,生成每个元素的处理Promise
    const promises = $(children).map(async function(index, elem) {
        const $elem = $(elem);
        const dataType = getDataType($elem.attr("type"));
        const content = await getContent(elem);
        
        console.log(`content ${index} :`, content);
        return { 
            nodeId: parseInt($elem.attr("id")), 
            content: content, 
            dataType: dataType 
        };
    }).get(); // 把jQuery对象转为普通数组

    // 等待所有Promise完成后返回结果数组
    return Promise.all(promises);
}

// 重构getContent:修复多文件处理逻辑,简化Promise返回
function getContent(elem) {
    const $elem = $(elem);
    const type = $elem.attr("type");

    if (type === "checkbox" || type === "radio") {
        return Promise.resolve($elem.is(":checked"));
    } else if (type === "file") {
        const files = Array.from($elem[0].files);
        
        if (files.length === 0) {
            return Promise.resolve(null); // 无文件时返回null
        } else if (files.length === 1) {
            return processFile(files[0]); // 单文件返回单个Base64
        } else {
            // 多文件返回Base64数组
            return Promise.all(files.map(file => processFile(file)));
        }
    } else {
        return Promise.resolve($elem.val());
    }
}

// 原readFileAsync逻辑保留
function readFileAsync(file) {
    return new Promise((resolve, reject) => {
        const reader = new FileReader();

        reader.onload = () => resolve(reader.result);
        reader.onerror = reject;

        reader.readAsDataURL(file);
    })
}

// 简化processFile:去掉冗余Promise嵌套
async function processFile(file) {
    try {
        const content = await readFileAsync(file);
        console.log(content);
        return content;
    } catch (err) {
        console.log(err);
        throw err;
    }
}

function ajaxCall(myVeryOwnDataObject, nodeID) {
    console.log(JSON.stringify(myVeryOwnDataObject));
    $.ajax({
        type: "POST",
        url: "/Umbraco/Api/Form/SendForm",
        contentType: "application/json; charset=utf-8",
        headers: { 'nodeId': nodeID },
        data: JSON.stringify(myVeryOwnDataObject),
        success: function (success) {
            console.log(success);
        },
        error: function (error) {
            console.log(error);
        }
    })
}

function getDataType(element) {
    switch (element) {
        case "text":
        case "email":
        case "tel":
        case "url":
        case "color":
            return "text";
        case "textarea":
            return "textarea";
        case "number":
        case "range":
            return "number";
        case "date":
        case "month":
            return "date";
        case "datetime-local":
            return "dateTime";
        case "time":
            return "time";
        case "file":
            return "file";
        case "checkbox":
        case "radio":
            return "check";
        default:
            return "text"; // 增加默认值,避免未匹配类型返回undefined
    }
}

关键改动说明

  • loopChildren:将each改为map生成Promise数组,用Promise.all等待所有异步操作完成,确保allData收集完所有表单数据后再传给AJAX。
  • getContent:修复多文件处理逻辑,支持返回单文件Base64或多文件Base64数组,简化Promise返回方式。
  • processFile:去掉冗余的Promise嵌套,用async/await简化异步流程,代码更清晰。
  • getDataType:合并相同返回值的case,增加默认值,避免未匹配类型返回undefined。

内容的提问来源于stack exchange,提问作者anvbis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 08:45:46