在Node.js中使用这种方法插入产品被认为是一种糟糕的做法吗?

klsxnrf1  于 12个月前  发布在  Node.js
关注(0)|答案(1)|浏览(70)

我使用Shopify API来侦听创建新产品时的事件。当我收到一个webhook时,我检索以下JSON数据:

{
    "admin_graphql_api_id": "gid://shopify/Product/8867427221826",
    "body_html": "<strong>Thshirt in verschiedenen farben</strong>",
    "created_at": "2023-10-14T10:51:06-04:00",
    "handle": "t-shirt",
    "id": 8867427221826,
    "product_type": "",
    "published_at": "2023-10-14T10:51:06-04:00",
    "template_suffix": "",
    "title": "T-shirt",
    "updated_at": "2023-10-14T10:51:08-04:00",
    "vendor": "crystelorbs",
    "status": "active",
    "published_scope": "global",
    "tags": "",
    "variants": [
        {
            "admin_graphql_api_id": "gid://shopify/ProductVariant/47150807122242",
            "barcode": "",
            "compare_at_price": null,
            "created_at": "2023-10-14T10:51:06-04:00",
            "fulfillment_service": "manual",
            "id": 47150807122242,
            "inventory_management": "shopify",
            "inventory_policy": "deny",
            "position": 1,
            "price": "29.95",
            "product_id": 8867427221826,
            "sku": "321dsfase1231321w",
            "taxable": true,
            "title": "34 / Blau",
            "updated_at": "2023-10-14T10:51:06-04:00",
            "option1": "34",
            "option2": "Blau",
            "option3": null,
            "grams": 0,
            "image_id": null,
            "weight": 0,
            "weight_unit": "kg",
            "inventory_item_id": 49189935579458,
            "inventory_quantity": 0,
            "old_inventory_quantity": 0,
            "requires_shipping": true
        },
        {
            "admin_graphql_api_id": "gid://shopify/ProductVariant/47150807187778",
            "barcode": "",
            "compare_at_price": null,
            "created_at": "2023-10-14T10:51:07-04:00",
            "fulfillment_service": "manual",
            "id": 47150807187778,
            "inventory_management": "shopify",
            "inventory_policy": "deny",
            "position": 2,
            "price": "29.95",
            "product_id": 8867427221826,
            "sku": "321dsfase1231321w-2",
            "taxable": true,
            "title": "33 / Blau",
            "updated_at": "2023-10-14T10:51:07-04:00",
            "option1": "33",
            "option2": "Blau",
            "option3": null,
            "grams": 0,
            "image_id": null,
            "weight": 0,
            "weight_unit": "kg",
            "inventory_item_id": 49189935644994,
            "inventory_quantity": 0,
            "old_inventory_quantity": 0,
            "requires_shipping": true
        },
        {
            "admin_graphql_api_id": "gid://shopify/ProductVariant/47150807220546",
            "barcode": "",
            "compare_at_price": null,
            "created_at": "2023-10-14T10:51:07-04:00",
            "fulfillment_service": "manual",
            "id": 47150807220546,
            "inventory_management": "shopify",
            "inventory_policy": "deny",
            "position": 3,
            "price": "29.95",
            "product_id": 8867427221826,
            "sku": "321dsfase1231321w-3",
            "taxable": true,
            "title": "12 / Blau",
            "updated_at": "2023-10-14T10:51:07-04:00",
            "option1": "12",
            "option2": "Blau",
            "option3": null,
            "grams": 0,
            "image_id": null,
            "weight": 0,
            "weight_unit": "kg",
            "inventory_item_id": 49189935677762,
            "inventory_quantity": 0,
            "old_inventory_quantity": 0,
            "requires_shipping": true
        }
    ],
    "options": [
        {
            "name": "Größe",
            "id": 11148870222146,
            "product_id": 8867427221826,
            "position": 1,
            "values": [
                "34",
                "33",
                "12"
            ]
        },
        {
            "name": "Farbe",
            "id": 11148870254914,
            "product_id": 8867427221826,
            "position": 2,
            "values": [
                "Blau"
            ]
        }
    ],
    "images": [
        {
            "id": 43049062433090,
            "position": 1,
            "product_id": 8867427221826,
            "width": 650,
            "height": 300,
            "alt": null,
            "src": "https://cdn.shopify.com/s/files/1/0757/6479/3666/files/ggg-modified_6dcaf2fa-d307-4ee7-bdf1-c7a9dbeefd62.png?v=1697295067",
            "created_at": "2023-10-14T10:51:07-04:00",
            "updated_at": "2023-10-14T10:51:07-04:00",
            "admin_graphql_api_id": "gid://shopify/ProductImage/43049062433090",
            "variant_ids": []
        }
    ],
    "image": {
        "id": 43049062433090,
        "position": 1,
        "product_id": 8867427221826,
        "width": 650,
        "height": 300,
        "alt": null,
        "src": "https://cdn.shopify.com/s/files/1/0757/6479/3666/files/ggg-modified_6dcaf2fa-d307-4ee7-bdf1-c7a9dbeefd62.png?v=1697295067",
        "created_at": "2023-10-14T10:51:07-04:00",
        "updated_at": "2023-10-14T10:51:07-04:00",
        "admin_graphql_api_id": "gid://shopify/ProductImage/43049062433090",
        "variant_ids": []
    }
}

我用交易创建产品。例如,一个产品可能有50个图像和30个变量值,这需要一个50倍的client.query('返回INTO ....')循环。
因为Node.js是单线程的,所以对数组中的每个图像使用for循环是一个坏主意吗?
我听说过工作线程,但我使用队列系统。当我使用队列系统时,我必须使用工作线程吗?
代码:

export const CreateProduct = async ({product, shop_id}: { product: _Product; shop_id: UUID; }): Promise<ReturnQuery> => {
  const client = await pool.connect();
  try {
    let product_options_data: {
      p_o_id: number;
      values: string[];
    }[] = [];

    await client.query('BEGIN');

    const Product: QueryResult = await client.query(`
      INSERT INTO product
      (info, name, status, shop_id)
      VALUES
      ($1, $2, $3, $4);
    `, [product.body_html, product.title, product.status, shop_id]);

    const p_id = Product.rows[0].id;

    if(product?.images) {
      for(let i = 0; i < product?.images?.length; i++) {
        await client.query('INSERT INTO product_media (p_id, src, alt, s_position) VALUES ($1, $2, $3, $4);', [p_id, product.images[i].src, product.images[i].alt, product.images[i].position]);
      }
    }

    if(product?.options) {
      if(product.options.length > 0) {
        for(let a = 0; a < product.options.length; a++) {
          if(product?.options[a].values) {
            const p_o_id: QueryResult = await client.query('INSERT INTO product_options (p_id, name, position) VALUES ($1, $2, $3);', [p_id, product.options[a].name, product.options[a].position]);
            product_options_data.push({
              p_o_id: p_o_id.rows[0].id,
              values: product.options[a].values as string[]
            })
          }
        }
      }
    }

    await client.query('COMMIT');
  } catch(e) {
    await client.query('ROLLBACK');
    console.log(e);
    Sentry.captureException(e);
    return {
      message: ErrorMessageQuery,
      statusCode: 500,
      query: 'SHOPIFY_CREATE_PRODUCT'
    }
  } finally {
    client.release();
  }
};

我想知道有没有什么方法可以改进我的代码。我听说建议将事务处理得很小,但如果一个产品有50个图像或许多变体,我必须循环遍历所有图像并将它们添加到我的数据库中。你能给我一些有用的提示,使这个解决方案更好吗?

t0ybt7op

t0ybt7op1#

您正在为每个磁盘使用await。很好在做所有这些工作时,你不会干扰JavaScript主循环。因此,服务器上的其他操作将在处理此操作时正常进行,即使需要一段时间。
而且,你在一个事务中执行操作(BEGIN/COMMIT),这对你的DBMS的性能很有帮助。
在我看来你做得对。👏
如果你有大量的这些东西,你可以将这个操作重构为服务流程从工作队列中完成的一些事情。但这是一个很大的变化,可能是不必要的,除非你的名字是WAL或MART。

相关问题