You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js微服务中Promise.all调用apolloFetch返回空查询错误求助

Fixing Empty Query Error with Promise.all & apolloFetch in Node.js Microservices

Let's break down the issues in your code that are causing the empty query error and fix them step by step:

Key Problems in Your Current Code

  • Premature resolve() call: You're calling resolve(results) before setting up and executing your Promise.all batch. Once resolve() is invoked, your GraphQL resolver's promise is marked as fulfilled, and any subsequent code runs independently—this can lead to incomplete execution or context issues that break your apolloFetch calls.
  • Incorrect apolloFetch parameter format: You're passing {p} to apolloFetch, which creates an object with a p key instead of the required query key. The remote GraphQL service can't find your query content, hence the empty query error.
  • Redundant JSON serialization/deserialization: Converting results to a string and back to JSON is unnecessary—results is already an array of objects from your database query.

Corrected Code

Here's the fixed version with explanations of critical changes:

const uri = "dsc.xxx.yyyy.com/abc/def/graphql"; 
const apolloFetch = CreateApolloFetch({uri}); 
const QryAllBooks = { 
  type: new GraphQLList(BookType), 
  args: {}, 
  resolve() { 
    return new Promise((resolve, reject) => { 
      const sql = singleLineString` 
        select distinct t.bookid,t.bookname,t.country 
        from books_tbl t 
        where t.ship_status = 'Not Shipped' 
      `; 
      pool.query(sql, (err, results) => { 
        if (err) {
          // Early return to avoid executing further code on error
          return reject(err); 
        }

        // Map results directly to apolloFetch promises (no redundant JSON conversion)
        const promises = results.map(book => {
          const bookId = book.bookid;
          const mutationQuery = `mutation updateShipping {
            updateShipping (id: ${bookId}, input:{ status: "Shipped" }) { 
              bookid bookname 
            }
          }`;
          // Pass query using the required "query" key
          return apolloFetch({ query: mutationQuery });
        });

        // Wait for all mutations to complete before resolving the resolver
        Promise.all(promises)
          .then(() => {
            console.log("All shipping status updates completed!");
            resolve(results); // Resolve with original results after mutations succeed
          })
          .catch((e) => {
            FunctionLogError(29, "Error", e);
            reject(e); // Ensure errors are propagated to the resolver
          }); 
      }); 
    }); 
  } 
}; 
module.exports = { QryAllBooks, BookType };

Additional Optimizations

1. Use Async/Await for Cleaner Code

If your Node.js environment supports async/await (Node 8+), rewrite the resolver to avoid promise nesting:

const QryAllBooks = { 
  type: new GraphQLList(BookType), 
  args: {}, 
  async resolve() { 
    try {
      // Wrap pool.query in a promise for async/await compatibility
      const results = await new Promise((resolveQuery, rejectQuery) => {
        const sql = singleLineString` 
          select distinct t.bookid,t.bookname,t.country 
          from books_tbl t 
          where t.ship_status = 'Not Shipped' 
        `;
        pool.query(sql, (err, res) => {
          if (err) rejectQuery(err);
          else resolveQuery(res);
        });
      });

      const promises = results.map(book => {
        const mutationQuery = `mutation updateShipping {
          updateShipping (id: ${book.bookid}, input:{ status: "Shipped" }) { 
            bookid bookname 
          }
        }`;
        return apolloFetch({ query: mutationQuery });
      });

      await Promise.all(promises);
      console.log("All shipping status updates completed!");
      return results;
    } catch (e) {
      FunctionLogError(29, "Error", e);
      throw e; // Throw error to let GraphQL handle it
    }
  } 
};

2. Avoid GraphQL Injection Risks with Variables

Directly interpolating bookId into your mutation string carries a small injection risk. Instead, use GraphQL variables for safer parameter passing:

const promises = results.map(book => {
  const mutationQuery = `
    mutation updateShipping($bookId: ID!, $status: String!) {
      updateShipping(id: $bookId, input:{ status: $status }) { 
        bookid bookname 
      }
    }
  `;
  return apolloFetch({
    query: mutationQuery,
    variables: {
      bookId: book.bookid,
      status: "Shipped"
    }
  });
});

This follows GraphQL best practices and eliminates any potential injection vulnerabilities.

内容的提问来源于stack exchange,提问作者Roger Dodger

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 03:59:31