Node.js async函数执行顺序异常,发送multipart/form-data POST请求如何调整代码?
代码调整方案
核心问题
原代码无法按预期执行的根本原因有三点:
- 异步读取图片的操作未等待完成就直接发起POST请求,导致提交的FormData缺失图片字段
- 原生
forEach方法不支持异步流程控制,无法保证任务按你期望的顺序执行 - 手动指定
multipart/form-data请求头缺少边界值(boundary),会导致后端无法正常解析表单内容
修改后完整代码
import axios from "axios"; import { readFileSync, PathOrFileDescriptor } from "fs"; import { readFile } from "fs/promises"; import FormData from "form-data"; import dotenv from "dotenv"; dotenv.config(); console.log("Parsing JSON data 💾"); const jsonData = readFileSync("data/data.json").toString(); const products: any[] = JSON.parse(jsonData).products; console.log("Products Store in JavaScript Object 🛒"); // 自执行异步函数包裹异步逻辑 (async () => { // 若不需要按顺序创建产品,可替换为Promise.all并发处理提升效率 for (let index = 0; index < products.length; index++) { const product = products[index]; console.log(`Creating Product ${index + 1}/${products.length} - ${product.name}`); const requestData = new FormData(); const imageReadTasks: Promise<void>[] = []; for (const [key, value] of Object.entries<any>(product)) { if (key.includes("image")) { console.log(`Converting ${key} in Image Blob 🖼`); // 收集所有图片读取任务 const readTask = readFile(value as PathOrFileDescriptor) .then(data => { requestData.append(key, data); console.log(`${key} Converted ✔`); }) .catch(err => { console.log(`${key} Failed to Convert ❌ - Error=${err}`); }); imageReadTasks.push(readTask); } else { requestData.append(key, key === "variants" ? JSON.stringify(value) : value); } } // 等待所有图片读取完成后再发起请求 await Promise.all(imageReadTasks); try { await axios.post( "http://localhost:8000/api/v1/product/create", requestData, { headers: { // 自动生成带boundary的表单请求头 ...requestData.getHeaders(), Cookie: `access_token=${process.env.ACCESS_TOKEN}; csrftoken=${process.env.CSRF_TOKEN}`, }, withCredentials: true, } ); console.log(`Product - ${product.name} Created ✔`); } catch (err: any) { console.log(`Product - ${product.name} Failed to create ❌`); console.log(err.response?.data || "Internal server error"); } } })();
关键改动说明
- 用
for...of替代forEach:支持配合await控制产品创建的顺序,若不需要顺序可将每个产品的处理逻辑封装为独立异步函数,用Promise.all并发执行大幅提升处理速度 - 等待所有异步任务完成:收集所有图片读取的Promise,用
Promise.all等待全部执行完成后再发起POST请求,保证提交的表单包含所有字段 - 自动生成表单请求头:调用
FormData实例的getHeaders()方法自动生成合法的表单请求头,避免手动配置缺失boundary导致的解析错误 - 简化文件读取逻辑:直接使用Node.js官方
fs/promises模块内置的promise化readFile方法,无需自行封装,稳定性更高
内容的提问来源于stack exchange,提问作者Damiisdandy
相关产品推荐
相关产品推荐

