简体   繁体   English

如何使用微应用 Node.js 模块处理 Shopify 的 API 调用限制

[英]How to handle Shopify's API call limit using microapps Node.js module

I have been banging my head finding an answer for this I just cant figure out.我一直在努力寻找答案,我只是想不通。 I am using a Node.js module for the Shopify API by microapps .我正在通过microapps为 Shopify API 使用 Node.js 模块。 I have a JSON object containing a list of product id's and skus that I need to update so I looping through the file and calling a function that calls the api.我有一个 JSON 对象,其中包含我需要更新的产品 ID 和 skus 列表,因此我遍历文件并调用调用 api 的函数。 Shopify's API limits calls to it and sends a response header with the value remaining. Shopify 的 API 限制对它的调用,并发送带有剩余值的响应标头。 This node modules provides an object containing the limits and usage.该节点模块提供了一个包含限制和使用的对象。 My question is based on the code below how to can at a setTimeout or similar when I am reaching the limit.我的问题是基于下面的代码,当我达到限制时如何在 setTimeout 或类似的时间。 Once you make your first call it will return the limits object like this:第一次调用后,它将返回如下所示的限制对象:

{
 remaining: 30,
 current: 10,
 max: 40
}

Here is what I have without respecting the limits as everything I tried fails:这是我在不尊重限制的情况下所做的,因为我尝试的一切都失败了:

const products = JSON.parse(fs.readFileSync('./skus.json','utf8'));

for(var i = 0;i < products.length; i++) {
  updateProduct(products[i]);
} 

function updateProduct(product){
    shopify.productVariant.update(variant.id, { sku: variant.sku })
    .then(result => cb(shopify.callLimits.remaining))
    .catch(err => console.error(err.statusMessage));
} 

I know I need to implement some sort of callback to check if the remaining usage is low and then wait a few seconds before calling again.我知道我需要实现某种回调来检查剩余使用量是否很低,然后等待几秒钟再调用。 Any help would be greatly appreciated.任何帮助将不胜感激。

I would use something to limit the execution rate of the function used by shopify-api-node ( Shopify.prototype.request ) to create the request, for example https://github.com/lpinca/valvelet . 我会用一些东西来限制shopify-api-nodeShopify.prototype.request )用来创建请求的函数的执行率,例如https://github.com/lpinca/valvelet

The code below is not tested but should work. 下面的代码没有经过测试但应该可行。 It should respect the limit of 2 calls per second. 它应该尊重每秒2个呼叫的限制。

var Shopify = require('shopify-api-node');
var valvelet = require('valvelet');

var products = require('./skus');

var shopify = new Shopify({
  shopName: 'your-shop-name',
  apiKey: 'your-api-key',
  password: 'your-app-password'
});

// Prevent the private shopify.request method from being called more than twice per second.
shopify.request = valvelet(shopify.request, 2, 1000);

var promises = products.map(function (product) {
  return shopify.productVariant.update(product.id, { sku: product.sku });
});

Promise.all(promises).then(function (values) {
  // Do something with the responses.
}).catch(function (err) {
  console.error(err.stack);
});

Try making use of the autoLimit option, for example:尝试使用autoLimit选项,例如:

import Shopify from 'shopify-api-node';

const getAutoLimit = (plan: string) => {
  if (plan === 'plus') {
    return { calls: 4, interval: 1000, bucketSize: 80 };
  } else {
    return { calls: 2, interval: 1000, bucketSize: 40 };
  }
};

const shopify = new Shopify({
  shopName: process.env.SHOPIFY_SHOP_NAME!,
  apiKey: process.env.SHOPIFY_SHOP_API_KEY!,
  password: process.env.SHOPIFY_SHOP_PASSWORD!,
  apiVersion: '2020-07',
  autoLimit: getAutoLimit(process.env.SHOPIFY_SHOP_PLAN),
});

export default shopify;

According to the library's documentation :根据图书馆的文档

- `autoLimit` - Optional - This option allows you to regulate the request rate
  in order to avoid hitting the [rate limit][api-call-limit]. Requests are
  limited using the token bucket algorithm. Accepted values are a boolean or a
  plain JavaScript object. When using an object, the `calls` property and the
  `interval` property specify the refill rate and the `bucketSize` property the
  bucket size. For example `{ calls: 2, interval: 1000, bucketSize: 35 }`
  specifies a limit of 2 requests per second with a burst of 35 requests. When
  set to `true` requests are limited as specified in the above example. Defaults
  to `false`.

And this is the version I tried: "shopify-api-node": "^3.3.2"这是我试过的版本: "shopify-api-node": "^3.3.2"

Regarding the rate limits, refer to Shopify's documentation .关于速率限制,请参阅Shopify 的文档

If you look at Shopify code, their github repository has a CLI. 如果你看一下Shopify代码,他们的github存储库就有了一个CLI。 That CLI is dealing with the limits. CLI正在处理限制。 You can quickly learn how Shopify deals with these limits, looking at their code. 您可以快速了解Shopify如何处理这些限制,查看其代码。

Since their code is in Ruby, it is pretty easy to digest. 由于他们的代码是在Ruby中,因此很容易消化。 It should not take a skilled JS programmer more than a few minutes to see how to deal with limits based on this code, even abstracting from Ruby. 它不应该让熟练的JS程序员花费几分钟时间来了解如何基于此代码处理限制,甚至从Ruby中抽象出来。

So my suggestion is to read that Shopify code and try and then morph your JS code to match the same pattern. 所以我的建议是阅读Shopify代码并尝试然后变形你的JS代码以匹配相同的模式。

try this...尝试这个...

const Shopify = require("shopify-api-node");

const waitonlimit = 2;
let calllimitremain = 40;

const shopify = new Shopify({
  shopName: process.env.SHOPIFY_URL,
  apiKey: process.env.SHOPIFY_KEY,
  password: process.env.SHOPIFY_PWD,
  autoLimit: true,
});

shopify.on("callLimits", (limits) => {
  calllimitremain = limits.remaining;
  if (limits.remaining < 10) {
    console.log(limits);
  }
});

exports.update = async () => {
  //Run this before update
  while (calllimitremain <= waitonlimit) {
    shopify.product.list({ limit: 1, fields: "id, title" });
    console.log(`Waiting for bucket to fill: ${calllimitremain}`);
  }

  //update
  await shopify.productVariant.update(
    onlineVariantId,
    { compare_at_price: price, price: promo }
  );
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM