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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 09:57:04