如何正确处理 Node.js gRPC 客户端和服务器之间的回调



我有一个简单的Express/gRPC项目,应该将硬编码的JSON对象打印到浏览器和控制台。问题是对象未及时返回到客户端以从 gRPC 服务器接收它。

我的项目实际上是对这个Codelabs项目的修改。不过,我只实现了listBooks方法,并将Go更改为Express。我能够成功地从Codelabs项目中的服务器获得响应。

起初,我想过避免回调,而是尝试承诺(承诺,承诺......(。但我没有成功。另外,从这个答案中,我现在知道节点 gRPC 没有实现为具有同步:

"节点 gRPC 没有同步调用。">

话虽如此,输出显示未收到数据。我需要做什么才能让客户端等待接收数据?

产品.原型

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;
}

服务器.js

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();

客户端.js

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;

客户端-服务器.js

const express = require('express');
const app = express();
var client = require('./client');
app.get('/', (req, res) => {
console.log('Hello World!');
client.listProducts();
res.send('Hello World!');
});
app.listen(3000, () =>
console.log('Example app listening on port 3000!'),
);

实际结果

gRPC 服务器显然已经具有该对象,但我将其打印到控制台只是为了好玩。客户端将其回调结果打印到控制台,但只打印一个空对象。

服务器.js输出

[ { id: 123, name: 'apple', price: '$2' } ]

客户端.js输出

Hello World!
{ products: [] }

要重现

  1. 打开2个终端,cd到项目
  2. 在一个终端中运行node server.js
  3. 在其他终端中运行node client-server.js
  4. 打开浏览器进行localhost:3000

这里的问题与同步操作与异步操作无关。

您尝试从服务器请求处理程序发送的对象与您在products.proto文件中声明的响应消息类型不匹配。响应消息类型ProductList是具有单个字段products的消息,该字段是重复的ProductObjects列表。因此,为了匹配您发送的对象应该是一个具有products字段的对象,该字段包含结构像ProductObject消息一样的对象数组。您拥有的代码几乎就在那里。您有数组,因此服务器处理程序代码应如下所示:

function listProduct(call, callback){
console.log(products);
callback(null, {products: products});
}

您已经对此有提示的输出。客户端接收的对象是{products: []},这是服务器应发送的对象的结构。

相关内容

最新更新