【问题标题】:Nodejs async functions not running in orderNodejs异步函数未按顺序运行
【发布时间】:2021-11-14 19:42:58
【问题描述】:

我正在尝试向我的后端发送POST 请求,此POST 请求需要multipart/form-data,因此我将图像位置转换为Buffers,然后将其全部作为POST 请求发送,但是由于 Nodejs async 的行为,我不知道如何让函数按顺序运行。我应该如何重新排列/重写这段代码?

import axios from "axios";
import { readFileSync, readFile as rf, PathOrFileDescriptor } from "fs";
import FormData from "form-data";
import dotenv from "dotenv";

dotenv.config();

// readfile promise
const readFile = (file: PathOrFileDescriptor) => {
  return new Promise((resolve, reject) => {
    rf(file, (err, data) => {
      if (err) reject(err.message);
      resolve(data);
    });
  });
};

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 ????");

products.forEach((product: any, index: number) => {
  console.log(
    `Creating Product ${index + 1}/${products.length} - ${product.name}`
  );

  let requestData = new FormData();
  for (const [key, value] of Object.entries<string>(product)) {
    if (key.includes("image")) {
      console.log(`Converting ${key} in Image Blob ????`);
      readFile(value)
        .then((data) => {
          requestData.append(key, data);
          console.log(`${key} Converted ✔`);
        })
        .catch((err) => {
          console.log(`${key} Failed to Convert ❌ - Error=${err}`);
        });
    } else {
      if (key === "variants") {
        requestData.append(key, JSON.stringify(value));
      } else {
        requestData.append(key, value);
      }
    }
  }
  axios
    .post("http://localhost:8000/api/v1/product/create", requestData, {
      headers: {
        "Content-Type": "multipart/form-data",
        Cookie: `access_token=${process.env.ACCESS_TOKEN}; csrftoken=${process.env.CSRF_TOKEN}`,
      },
      withCredentials: true,
    })
    .then(() => {
      console.log(`Product - ${product.name} Created ✔`);
    })
    .catch((err) => {
      console.log(`Product - ${product.name} Failed to create ❌`);
      if (err.response) {
        console.log(err.response.data);
      } else {
        console.log("Internal server error");
      }
    });
});

我正在解析的数据是一个类似这样的对象数组

{
      "store": "maki-2",
      "name": "Nike Sportwear Down-fill Windrunner Jacket",
      "description": "The Nike Sportswear Jacket warms up your winter wardrobe with a serious supply of down. This lightweight zip-up style features water-resistant and windproof Nike Shield technology to help keep you comfortable in rough weather. A subtle chevron design, which references the OG Windrunner, graces the chest.",
      "brand": "Nike",
      "gender": "U",
      "category": "outwear",
      "image_v0_1": "data/images/outwear/Nike Sportswear Down-Fill Windrunner/sportswear-down-fill-windrunner-jacket-hHNjxL (3).png",
      "image_v0_2": "data/images/outwear/Nike Sportswear Down-Fill Windrunner/sportswear-down-fill-windrunner-jacket-hHNjxL.jpg",
      "image_v0_3": "data/images/outwear/Nike Sportswear Down-Fill Windrunner/sportswear-down-fill-windrunner-jacket-hHNjxL.png",
      "image_v1_1": "data/images/outwear/Nike Sportswear Down-Fill Windrunner/sportswear-down-fill-windrunner-jacket-hHNjxL (1).jpg",
      "image_v1_2": "data/images/outwear/Nike Sportswear Down-Fill Windrunner/sportswear-down-fill-windrunner-jacket-hHNjxL (1).png",
      "image_v1_3": "data/images/outwear/Nike Sportswear Down-Fill Windrunner/sportswear-down-fill-windrunner-jacket-hHNjxL (2).png",
      "variants": [
        {
          "is_default": false,
          "price": 23000,
          "quantity": 23,
          "size": "M",
          "color": "multi-colored"
        },
        {
          "is_default": true,
          "price": 25000,
          "quantity": 23,
          "size": "L",
          "color": "black"
        }
      ]
    },

【问题讨论】:

标签: javascript node.js asynchronous async-await multipartform-data


【解决方案1】:

您应该在 for 循环中链接承诺。

var readFilePromise = Promise.resolve();

for (const [key, value] of Object.entries < string > product) {
  if (key.includes("image")) {
    console.log(`Converting ${key} in Image Blob ?`);
    readFilePromise = readFilePromise
      .then(() => readFile(value))
      .then((data) => {
        requestData.append(key, data);
        console.log(`${key} Converted ✔`);
      })
      .catch((err) => {
        console.log(`${key} Failed to Convert ❌ - Error=${err}`);
      });
  } else {
    if (key === "variants") {
      requestData.append(key, JSON.stringify(value));
    } else {
      requestData.append(key, value);
    }
  }
}

您的POST 请求只能在承诺解决后提出。

readFilePromise.then(() => {
  axios.post(...)
})

【讨论】:

    【解决方案2】:

    您可以使用Promise.all 等待地图函数内的所有承诺完成:

    import axios from "axios";
    import {
      readFileSync,
      readFile as rf,
      PathOrFileDescriptor
    } from "fs";
    import FormData from "form-data";
    import dotenv from "dotenv";
    
    dotenv.config();
    
    // readfile promise
    const readFile = (file: PathOrFileDescriptor) => {
      return new Promise((resolve, reject) => {
        rf(file, (err, data) => {
          if (err) reject(err.message);
          resolve(data);
        });
      });
    };
    
    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 ?");
    
    
    await Promise.all(
      products.map(async(product: any, index: number) => {
        console.log(
          `Creating Product ${index + 1}/${products.length} - ${product.name}`
        );
    
        let requestData = new FormData()
    
        Object.keys(product).map(async(key: any) => {
          if (key.includes("image")) {
            try {
              const data = await readFile(product[key])
              requestData.append(key, data)
              console.log(`${key} Converted ✔`);
            } catch (e) {
              console.log(`${key} Failed to Convert ❌ - Error=${e}`);
            }
          } else {
            if (key === "variants") {
              requestData.append(key, JSON.stringify(value));
            } else {
              requestData.append(key, value);
            }
          }
    
          return key;
        });
    
        await axios
          .post("http://localhost:8000/api/v1/product/create", requestData, {
            headers: {
              "Content-Type": "multipart/form-data",
              Cookie: `access_token=${process.env.ACCESS_TOKEN}; csrftoken=${process.env.CSRF_TOKEN}`,
            },
            withCredentials: true,
          })
          .then(() => {
            console.log(`Product - ${product.name} Created ✔`);
          })
          .catch((err) => {
            console.log(`Product - ${product.name} Failed to create ❌`);
            if (err.response) {
              console.log(err.response.data);
            } else {
              console.log("Internal server error");
            }
          });
        return product;
      })
    );

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-30
      • 2021-05-07
      相关资源
      最近更新 更多