使用WooCommerce API获取Node.js产品数据返回重复项求助
WooCommerce API分页返回重复产品的解决思路
1. 修复URL参数的转义错误
你的代码中请求URL错误使用了HTML实体&分隔参数,这会导致WooCommerce API无法正确解析page参数,实际每次请求都在拉取第一页数据,这是重复产品的核心诱因。
将代码中的URL模板字符串里的&替换为&:
const result = await WooCommerce.getAsync(`products?per_page=100&page=${page}&orderby=id&order=asc`);
2. 用ID范围分页替代页码分页
页码分页在产品数据动态变化(比如同步时产品被修改、新增)时极易出现重复或遗漏,改用ID范围查询可彻底规避这个问题:
async function fetchAllProducts() { let lastId = 0; let allProducts = []; let productSKUs = new Set(); let productIDs = new Set(); while (true) { try { // 筛选ID大于lastId的产品,确保每次拉取未获取过的数据 const result = await WooCommerce.getAsync(`products?per_page=100&orderby=id&order=asc&after=${lastId}`); await delay(1500); const data = JSON.parse(result.toJSON().body); if (data.length === 0) { break; } console.log(`Fetched ${data.length} products starting from ID ${lastId + 1}`); let uniqueCount = 0; data.forEach(product => { if (!productIDs.has(product.id)) { productIDs.add(product.id); productSKUs.add(product.sku); allProducts.push(product); displayProductDetails(product); uniqueCount++; // 更新lastId为当前批次最大的产品ID lastId = Math.max(lastId, product.id); } else { console.log(`Duplicate found: ID = ${product.id}`); } }); console.log(`Unique products added: ${uniqueCount}`); await delay(3000); } catch (error) { console.error('Error fetching products:', error); break; } } console.log('Fetched products count:', allProducts.length); console.log('Unique SKUs count:', productSKUs.size); console.log('Unique IDs count:', productIDs.size); return allProducts; }
注:
after参数在WooCommerce REST API v3中用于筛选ID大于指定值的产品,确保请求数据无重叠。
3. 验证分页元数据的正确性
每次请求后打印返回头中的x-wp-total(总产品数)和x-wp-totalpages(总页数),确认分页逻辑是否正常:
console.log(`Total pages: ${result.headers['x-wp-totalpages']}`); console.log(`Current page: ${page}`);
如果总页数计算异常,需排查服务器端问题:
- 是否有自定义
woocommerce_rest_product_query钩子修改了产品查询条件? - 是否拉取了草稿、回收站状态的产品?可添加
status=publish参数明确获取已发布产品:products?per_page=100&page=${page}&orderby=id&order=asc&status=publish
4. 排除客户端库的问题
尝试用axios等原生HTTP库发起请求,绕过woocommerce-api库,确认是否是库的参数处理或签名问题:
const axios = require('axios'); const crypto = require('crypto'); // 生成WooCommerce API所需的OAuth1.0认证头 function generateAuthHeader(url, method) { const params = { oauth_consumer_key: 'ck_1234', oauth_nonce: crypto.randomBytes(16).toString('hex'), oauth_signature_method: 'HMAC-SHA256', oauth_timestamp: Math.floor(Date.now() / 1000).toString(), oauth_version: '1.0' }; const sortedParams = Object.keys(params).sort().map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`).join('&'); const baseString = `${method.toUpperCase()}&${encodeURIComponent(url)}&${encodeURIComponent(sortedParams)}`; const signingKey = `${encodeURIComponent('cs_1234')}&`; const signature = crypto.createHmac('sha256', signingKey).update(baseString).digest('base64'); params.oauth_signature = signature; return `OAuth ${Object.keys(params).map(key => `${key}="${encodeURIComponent(params[key])}"`).join(', ')}`; } async function fetchWithAxios(page) { const url = `https://my-website.com/wp-json/wc/v3/products?per_page=100&page=${page}&orderby=id&order=asc`; const headers = { 'Authorization': generateAuthHeader(url, 'GET') }; const response = await axios.get(url, { headers }); return response.data; }
如果用axios请求无重复,说明woocommerce-api库存在缺陷,可考虑更换库。
5. 排查服务器端缓存与性能问题
即便你已禁用缓存,仍需确认:
- 服务器反向代理(如Nginx)是否缓存了API请求?可添加
Cache-Control: no-cache头强制跳过缓存:
const result = await WooCommerce.getAsync(`products?per_page=100&page=${page}&orderby=id&order=asc`, { headers: { 'Cache-Control': 'no-cache' } });
- 服务器负载过高是否导致数据库分页查询返回错误结果?检查服务器CPU、内存使用率,以及数据库慢查询日志,确认分页查询是否正常执行。
内容的提问来源于stack exchange,提问作者newbie
相关产品推荐
相关产品推荐

