基本上,无论我做什么,从我的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
答案 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
对象的数组。方法实现中的所有代码都旨在返回该字段中的字符串,而这不会导致对象兼容。