A space to discuss GraphQL queries, mutations, troubleshooting, throttling, and best practices.
I have created a recursive function to get all the products in a shop by inserting the cursor of the last node received as the "after" filter of the next query. However, the function always receives the same first set of products and continues in an infinite loop. It appears the "after" filter is not being used to run the query. The query appears to run correctly when run using the GraphiQL app in the shop so it could be that I am doing something wrong.
function _getAllShopProducts({defaultProductFields, fields, products=[], cursor=null}) {
return new Promise((resolve, reject)=>{
const fetchedFields = fields.length ? fields : defaultProductFields;
const fragment = `
fragment productFields on Product {
${fetchedFields.join(' ')}
}
`;
const queryPrefix = `
query getAllShopProducts ($first: Int!, $cursor: String){
products(first: $first, after: $cursor) {
pageInfo {
hasNextPage
}
edges {
cursor
node {
...productFields
}
}
}
}
`;
const first = 250;
const variables = {first, cursor};
const fullQuery = queryPrefix + fragment;
this.ShopifyGQL // prepares the request to the Shopify GraphQL endpoint by setting headers and access code
.send(JSON.stringify({query:fullQuery, variables}))
.then((res)=>{
const edges = res.body.data.products.edges;
cursor = edges[edges.length-1].cursor; // set cursor to last node
let returnedProducts = [];
edges.forEach((edge)=>{
returnedProducts.push(edge.node);
})
// update products list
products = products.concat(returnedProducts);
// if there are no more pages, return the result
const hasNextPage = res.body.data.products.pageInfo.hasNextPage;
if(hasNextPage){
// recurse
return resolve(_getAllShopProducts.bind(this)({defaultProductFields, fields, products, cursor}))
} else {
return resolve(products);
}
})
})
}
Hey @Tolulope_Akinol
Have you confirmed that $cursor is getting set correctly in your code below? You mentioned it works fine in GraphiQL and based on what I see, the query seems valid. My guess is the cursor isn't being set correctly or potentially is null in your code below which is why it loops infinitely.
Kevin_A | Solutions Engineer @ Shopify
- Was my reply helpful? Click Like to let me know!
- Was your question answered? Mark it as an Accepted Solution
- To learn more visit Shopify.dev or the Shopify Web Design and Development Blog
Thanks for the reply.
Yes, I did console.log the cursor variable to see that it was set correctly and it was.
Hey @Tolulope_Akinol
Thanks for confirming. If the request you are sending from your app is identical to the request you are sending in GraphiQL, then the results will also be identical. If you hardcode the query in your code and ignore the recursive part of your function, does it return the expected results?
Kevin_A | Solutions Engineer @ Shopify
- Was my reply helpful? Click Like to let me know!
- Was your question answered? Mark it as an Accepted Solution
- To learn more visit Shopify.dev or the Shopify Web Design and Development Blog
@Kevin_A It works when hard coded but not when I send the cursor as a variable
This works
const query = `
query getAllShopProducts {
products(first: 1, after: "eyJsYXN0X2lkIjo1NzQ0Nzc1MzMxOTg5LCJsYXN0X3ZhbHVlIjoiNTc0NDc3NTMzMTk4OSJ9") {
pageInfo {
hasNextPage
}
edges {
cursor
node {
id
productType
handle
}
}
}
}
`;
this.ShopifyGQL
.send(JSON.stringify({query}))
But not this
const cursor = "eyJsYXN0X2lkIjo1NzQ0Nzc1MzMxOTg5LCJsYXN0X3ZhbHVlIjoiNTc0NDc3NTMzMTk4OSJ9"
const query = `
query getAllShopProducts ($cursor: String!) {
products(first: 1, after: $cursor) {
pageInfo {
hasNextPage
}
edges {
cursor
node {
id
productType
handle
}
}
}
}
`;
const variables = {cursor};
this.ShopifyGQL
.send(JSON.stringify({query, variables}))
Never mind. The issue was that I was reusing the same request over iterations so the parameters of the very first request would carry over to all the subsequent ones. I solved the problem by creating a new request each time