从gRPC服务器返回的空对象

时间:2019-08-01 11:30:50

标签: javascript node.js express grpc

基本上,无论我做什么,从我的gRPC服务器中的回调返回的JSON对象都是空的。

在大多数情况下,我都在遵循this教程,但我使用的是SQLite3服务器而不是knex,并且已经使用了 listProducts 方法。我还没有尝试过其他产品方法。


server.js 中,我从SQLite3数据库中获取了一些数据,并尝试在回调中将其返回(位于方法的底部)。我还从数据库中打印出数据,以确认我实际上正在获取有效数据。

gRPC server.js

function listProducts(call, callback) {
  console.log("******** Listed the products *********");
  var data = "";

  let db = new sqlite3.Database('../data/testDB.db', sqlite3.OPEN_READONLY, (err) => {
    if(err){
    console.error(err.message);
    }
    console.log("connected to DB");
  });

  db.serialize(() => {
    db.get('SELECT NAME as name FROM PEEPS', (err, row) => {
          if(err){
            console.error(err.message);
          }
          console.log(row.name);
          data.name = row.name;
    });
  });

  db.close((err) => {
    if(err) {
      console.error(err.message);
    }
    console.log('closed db');
  });

  callback(null, { products:  data.name });
}

gRPC server.js

的输出
******** Listed the products *********
connected to DB
Jeff            // Correct data from DB. 
closed db

该回调返回到调用它的 client.js 。但是,该对象始终为空。

如果我取消注释 res.json({name:“ jessie”}); 并注释 res.json(result); ,代码将按预期工作; 名称:jessie 作为JSON对象发送到浏览器。

因此,这告诉我从客户端到浏览器的数据均已正确处理。因此,问题在于何时将数据从 server.js 传递到 client.js

gRPC client.js

// requirements
const path = require('path');
const protoLoader = require('@grpc/proto-loader');
const grpc = require('grpc');

// gRPC client
const productProtoPath = path.join(__dirname, '..', '..', 'protos', 'product.proto');
const productProtoDefinition = protoLoader.loadSync(productProtoPath);
const productPackageDefinition = grpc.loadPackageDefinition(productProtoDefinition).product;
const client = new productPackageDefinition.ProductService('localhost:50051', grpc.credentials.createInsecure());

// handlers
const listProducts = (req, res) => {
  client.listProducts({}, (err, result) => {
      console.log(result);
      console.log(typeof result);
      // console.log(res.json(result));
      res.json(result);
      // res.json({ name: "jessie" });
      console.log("*******************");
  });
};

gRPC client.js

的输出
Server listing on port 3000
{}                 //Oh no! An empty JSON object!
object
*******************

修改 这是我的存储库的链接:https://github.com/burke212/grpc-node

1 个答案:

答案 0 :(得分:0)

这里的主要问题是在服务器代码中,您的db方法是异步的,但是您试图同步访问结果。您需要在listProducts的回调中调用db.get的主回调,以确保在尝试使用数据库请求之前获得该数据库请求的结果。进行此更改后,您的listProducts方法实现应如下所示:

function listProducts(call, callback) {

  let db = new sqlite3.Database('../data/testDB.db', sqlite3.OPEN_READONLY);

  db.serialize(() => {
    db.get('SELECT NAME as name FROM PEEPS', (err, row) => {
          if(err){
            console.error(err.message);
          }
          // Call the callback here to use the result of db.get
          callback(null, { products:  row.name });
    });
  });

  db.close();

}

为简单起见,我省略了日志记录。另外,在sqlite3.Database自述文件的示例中,db.close构造函数和sqlite3没有回调。我建议再次检查这些函数是否真正接受回调。

除此之外,既然您已经共享了定义服务的product.proto文件,那么还有另一个问题。 listProducts服务中的ProductService方法被声明为返回ProductList对象。在该消息类型中,products字段必须是Product对象的数组。方法实现中的所有代码都旨在返回该字段中的字符串,而这不会导致对象兼容。