0

I'm trying to use apolloFetch inside a Promise.all in my Node.js microservice but keep getting an error that the query is empty. The reason for using apolloFetch is to call another micro service and pass it an array of queries. Can someone give me some direction? My code is as follows:

   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) => {
            let 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) {
                    reject(err);
                }
                resolve(results);
                const str = JSON.stringify(results);
                const json = JSON.parse(str);
                const promises = [];
                for (let p = 0; p < results.length; p++) {
                    const book_id = json[p].bookid;
                    const query = `mutation updateShipping
                              {updateShipping
                               (id: ${book_id}, input:{
                                  status: "Shipped"
                               })
                               { bookid
                                 bookname }}`;
                    promises.push(query);
                }
                //Below is the Promise.all function with the   
                //apolloFetch that calls another graphql endpoint
                //an array of queries
                Promise.all(promises.map(p => apolloFetch({p}))).then((result) => {
                    //this is the problem code^^^^^^^^^^^^^^^^^^^^^ 
                    resolve();
                    console.log("success!");
                }).catch((e) => {
                    FunctionLogError(29, "Error", e);
                });
            });
        });
    }
};
module.exports = {
    QryAllBooks,
    BookType
};
Roger Dodger
  • 927
  • 2
  • 16
  • 37

2 Answers2

1

It looks like apolloFetch requires query - you are passing p

change

Promise.all( promises.map(p=>apolloFetch({p})) )

to

Promise.all( promises.map(query=>apolloFetch({query})) )

You also call resolve twice

To resolve all errors or success

const final_results = []
Promise.all(promises.map(query => apolloFetch({
  query,
}))).then((result) => {
  final_results.push(result)
}).catch((e) => {
  final_results.push(e)
}).then(() => {
  resolve(final_results)
});
Steven Kaspar
  • 1,147
  • 10
  • 14
  • if you mean calling resolve inside the Promise.all block - I have that in there in order to pass my eslint tests which fails it's test if there is nothing inside that block. Could you suggest how to overcome that or maybe I'm doing the Promise.all itself wrong? – Roger Dodger Feb 27 '19 at 17:03
  • 1
    I think you are misunderstanding how the `{p}` syntax works. That is ES6 "shorthand" for `{ p: p }` - what `apolloFetch` is expecting is an object with a `query` key. So you need to pass `{ query }` with a change in name or `{ query: p }` to pass the correct object that apolloFetch expects – Steven Kaspar Feb 27 '19 at 17:29
  • 1
    I would also change the `promises` array to `queries` because that is an array of queries and in your `map` you are returning the `promise` which is returned from `apolloFetch` – Steven Kaspar Feb 27 '19 at 17:30
  • No I got that part - I changed from p to query, and it is working now. Your answer solved my issue. Now I have to iron out some bugs like how to properly resolve that specific call and do the error logging so that I can log ALL the errors instead of just one error that might return (in other words, I have figure out a way to make sure that the entire array of queries runs, with those that failed being passed into a logger function). – Roger Dodger Feb 27 '19 at 18:34
  • 1
    Idk if that is what you are looking for but the edit shows how you can get all the responses and send them back – Steven Kaspar Feb 27 '19 at 18:56
  • Will give it a try and see if it does what I need; if not, will create another question and post the link. thanks. – Roger Dodger Feb 27 '19 at 19:36
  • I posted another question specifically for error catching here: https://stackoverflow.com/questions/54914590/how-to-correctly-trap-and-read-any-errors-generated-in-a-promise-all-call – Roger Dodger Feb 27 '19 at 21:14
1

You immediately resolve or rejects once the pool.query() callback starts:

if(err){ reject(err);}resolve(results);

So unless the query fails, you never resolve with the results from the apolloFetch calls, since the promise is already resolved with the pool.query() results. I guess you're missing an else block:

if( err ) {
  reject();
}
else {
  const promises = ...
}

PS: you can try using node.js' util.promisify() to turn pool.query() into a promise as well so you can just write something resembling: query(...).then(results=>results.map(apolloFetch) instead of ahving to mix callbacks and promises.

Shilly
  • 8,511
  • 1
  • 18
  • 24
  • pool.query is that standard that rest of my team is using and if I change that pattern, I'll get frowned upon. To you first part - the pool.query is for the 1st query that returns rows that populate an array called promises[]. The apolloFetch is actually calling another micro-service endpoint with a mutation query. With that said, am I still doing something wrong in the pool.query and it's if clause? – Roger Dodger Feb 27 '19 at 17:01