title: How to correctly handle callbacks between Node.js gRPC client & server
body: <p>I have a simple Express/ gRPC project that's supposed to print a hard coded JSON object to the browser &amp; console. The problem is that the object isn't returned to the client in time to receive it from the gRPC server. </p>
  
  <p>My project is actually a modification of <a href="https://codelabs.developers.google.com/codelabs/cloud-grpc/index.html?index=..%2F..index#0" rel="nofollow noreferrer">this Codelabs</a> project. I've only implemented the <code>listBooks</code> method though, and have changed Go to Express. I was able to successfully get a response from the server in the Codelabs project. </p>
  
  <p>At first I thought about avoiding callbacks, and trying promises (promises, promisfy...) instead. But I haven't had success. Also, from <a href="https://stackoverflow.com/questions/46318298/grpc-with-synchronous-calls-in-node-application">this</a> answer, I now know that Node gRPC isn't implemented to have sync:</p>
  
  <blockquote>
    <p>"Node gRPC does not have synchronous calls." - murgatroid99</p>
  </blockquote>
  
  <p>With that said, the output is showing that the data isn't being received. What do I need to do to have the client wait for the data to be available to be received? </p>
  
  <p><strong>products.proto</strong></p>
  
  <pre class="lang-proto prettyprint-override"><code>syntax = "proto3";
  
  package products;
  
  service ProductService {
    rpc ListProduct (Empty) returns (ProductList) {}
  }
  
  message Empty {}
  
  message Product {
    int32 id = 1;
    string name = 2;
    string price = 3;
  }
  
  message ProductList {
    repeated Product products = 1;
  }
  </code></pre>
  
  <p><strong>server.js</strong></p>
  
  <pre><code>var PROTO_PATH = __dirname + '/products.proto';
  var grpc = require('grpc');
  var protoLoader = require('@grpc/proto-loader');
  var packageDefinition = protoLoader.loadSync(
      PROTO_PATH,
      {
          keepCase: true,
          longs: String,
          enums: String,
          defaults: true,
          oneofs: true
      });
  var productsProto = grpc.loadPackageDefinition(packageDefinition).products;
  
  
  var products = [{
      id: 123,
      name: 'apple',
      price: '$2'
  }];
  
  
   function listProduct(call, callback){
       console.log(products);
       callback(null, products);
   }
  
  
  function main(){
      var server = new grpc.Server();
  
      server.addService(productsProto.ProductService.service, 
          {ListProduct: listProduct}
      );
  
      server.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure());
      console.log("server started");
      server.start();
  }
  
  main();
  </code></pre>
  
  <p><strong>client.js</strong></p>
  
  <pre><code>var PROTO_PATH = __dirname + '/products.proto';
  var grpc = require('grpc');
  var protoLoader = require('@grpc/proto-loader');
  var packageDefinition = protoLoader.loadSync(
      PROTO_PATH,
      {
          keepCase: true,
          longs: String,
          enums: String,
          defaults: true,
          oneofs: true
      });
  
  var products = grpc.loadPackageDefinition(packageDefinition).products;
  var client = new products.ProductService('localhost:50051', grpc.credentials.createInsecure());
  
  
  function printResponse(error, response){
      if(error){
          console.log('Error: ', error);
      }
      else{
          console.log(response);
      }
  }
  
  function listProducts() {   
      client.listProduct({}, function(error, products){
           printResponse(error, products);
      });
  }
  
  
  exports.listProducts = listProducts;
  </code></pre>
  
  <p><strong>client-server.js</strong></p>
  
  <pre><code>const express = require('express');
  const app = express();
  var client = require('./client');
  
  app.get('/', (req, res) =&gt; {
      console.log('Hello World!');
      client.listProducts();
      res.send('Hello World!');
  });
  
  app.listen(3000, () =&gt;
    console.log('Example app listening on port 3000!'),
  );
  </code></pre>
  
  <h2>Actual Result</h2>
  
  <p>The gRPC server obviously already has the object, but I print it to console just for fun. The client prints its callback result to the console, but is only printing an empty object.  </p>
  
  <p><strong>server.js Output</strong></p>
  
  <pre><code>[ { id: 123, name: 'apple', price: '$2' } ]
  </code></pre>
  
  <p><strong>client.js Output</strong></p>
  
  <pre><code>Hello World!
  { products: [] }
  </code></pre>
  
  <h2>To Reproduce</h2>
  
  <ol>
  <li>Open 2 terminals, <code>cd</code> to project</li>
  <li>Run <code>node server.js</code> in one terminal</li>
  <li>Run <code>node client-server.js</code> in the other terminal</li>
  <li>Open a browser to <code>localhost:3000</code></li>
  </ol>