如何将Shopify所有商品分页获取并合并到单个数组?
Shopify REST API分页获取全部商品失败修复
问题背景
Shopify REST API采用分页返回商品数据,默认每页50条,最多可设置250条,需通过响应头中的Link字段获取下一页链接,多次调用才能拉取全部数据。当前代码仅能正确加载第一页,约1300个商品无法全部合并到allProducts数组,且反复输出同一个下一页链接,无法继续翻页。
代码问题分析
- 分页方式混用:同时使用了
since_id和page_info两种分页逻辑,Shopify REST API推荐使用page_info(通过Link头)进行分页,两种方式混用会导致逻辑混乱。 - 正则表达式错误:原正则
/<[^;]+/(\w+\.json[^;]+)>;\srel="next"/存在转义错误,且拼接URL的方式容易出错,应该直接提取<>包裹的完整下一页链接。 - 异步逻辑漏洞:递归调用
makeRequest时未返回Promise,导致外层Promise无法等待递归完成,无法正确触发最终的resolve。 - 变量逻辑混乱:
since_id未更新,且products变量在不同分支的赋值逻辑冲突,非第一页的SDK调用逻辑未正确执行。
修复后的代码
import { shopify } from './testingShopifyApp.js'; import { session } from './testingShopifyApp.js'; import "@shopify/shopify-api/adapters/node"; const client = new shopify.clients.Rest({ session }); let allProducts = []; /** * 通过Shopify REST API分页获取全部商品 * @param {string|null} nextPageInfo - 下一页的page_info参数,首次调用传null * @returns {Promise<Array>} 全部商品数组 */ async function fetchAllProducts(nextPageInfo = null) { const queryParams = { limit: 250, // 用最大分页上限减少请求次数 fields: 'id,title,images', }; // 如果有下一页的page_info,添加到查询参数 if (nextPageInfo) { queryParams.page_info = nextPageInfo; } try { const response = await shopify.rest.Product.all({ session, query: queryParams, }); // 合并当前页商品到总数组 allProducts = allProducts.concat(response.data); console.log(`已获取 ${allProducts.length} 个商品`); // 解析Link头,提取下一页的page_info const linkHeader = response.headers.Link?.[0]; if (linkHeader) { // 修正正则:提取rel="next"对应的page_info const nextMatch = linkHeader.match(/<[^>]+page_info=([^&>]+)>;\s*rel="next"/); if (nextMatch) { // 递归调用获取下一页 await fetchAllProducts(nextMatch[1]); } } return allProducts; } catch (error) { console.error('获取商品失败:', error); throw error; } } // 启动获取全部商品 fetchAllProducts() .then((products) => { console.log('全部商品获取完成,总数:', products.length); // 这里可以处理全部商品数据 }) .catch((err) => { console.error('流程出错:', err); });
修复关键点说明
- 统一分页方式:使用Shopify推荐的
page_info分页,通过解析响应头的Link字段获取下一页标识,避免since_id的局限性。 - 修正正则匹配:直接从
Link头中提取page_info参数,无需拼接URL,避免路径错误。 - 异步流程优化:使用
async/await替代Promise嵌套,递归调用时等待异步完成,确保全部数据加载完成后再返回结果。 - 简化逻辑:去掉冗余的
fetch调用和since_id变量,统一使用Shopify SDK的Product.all方法,减少逻辑冲突。
内容的提问来源于stack exchange,提问作者Cracker_Jack_5943
相关产品推荐
相关产品推荐

