【问题标题】:How to correctly handle callbacks between Node.js gRPC client & server如何正确处理 Node.js gRPC 客户端和服务器之间的回调
【发布时间】:2019-08-15 14:17:36
【问题描述】:

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

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

起初我想避免回调,而是尝试使用 promises (promises, promisfy...)。但我没有成功。另外,从this 的回答中,我现在知道 Node gRPC 没有实现同步:

“节点 gRPC 没有同步调用。” - murgatroid99

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

products.proto

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

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

client.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;

client-server.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 服务器显然已经拥有该对象,但我将其打印到控制台只是为了好玩。客户端将其回调结果打印到控制台,但仅打印一个空对象。

server.js 输出

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

client.js 输出

Hello World!
{ products: [] }

复制

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

【问题讨论】:

    标签: node.js express grpc


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 谢谢!我真的很感谢你的帮助。你不知道我处理这个问题有多久了。
    猜你喜欢
    • 1970-01-01
    • 2018-07-18
    • 2013-08-10
    • 2022-11-16
    • 1970-01-01
    • 2023-03-19
    • 2014-03-24
    • 2013-10-30
    • 1970-01-01
    相关资源
    最近更新 更多