从 gRPC 服务器返回的空对象

Ado*_*nis 5 javascript node.js express grpc

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

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


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

gRPC 服务器.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 });
}
Run Code Online (Sandbox Code Playgroud)

gRPC server.js的输出

******** Listed the products *********
connected to DB
Jeff            // Correct data from DB. 
closed db
Run Code Online (Sandbox Code Playgroud)

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

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

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

gRPC 客户端.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("*******************");
  });
};
Run Code Online (Sandbox Code Playgroud)

gRPC client.js的输出

Server listing on port 3000
{}                 //Oh no! An empty JSON object!
object
*******************
Run Code Online (Sandbox Code Playgroud)

编辑 这里是我的存储库的链接:https ://github.com/burke212/grpc-node

mur*_*d99 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();

}
Run Code Online (Sandbox Code Playgroud)

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

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