| // this example demonstrates how to consume a streaming rpc service. |
| |
| /*eslint-disable strict, no-console*/ |
| var protobuf = require(".."); |
| |
| // Load a definition with services: |
| |
| var root = protobuf.Root.fromJSON({ |
| nested: { |
| Greeter: { |
| methods: { |
| "SayHello": { |
| requestType: "Hello", |
| requestStream: true, |
| responseType: "World", |
| responseStream: true |
| } |
| } |
| }, |
| Hello: { |
| fields: { |
| name: { |
| type: "string", |
| id: 1 |
| } |
| } |
| }, |
| World: { |
| fields: { |
| message: { |
| type: "string", |
| id: 1 |
| } |
| } |
| } |
| } |
| }); |
| |
| // Get its types: |
| |
| var Greeter = root.lookup("Greeter"), |
| Hello = root.lookup("Hello"), |
| World = root.lookup("World"); |
| |
| // Provide a stream-aware RPC implementation: |
| |
| var greeter = Greeter.create(/* rpcImpl */ (function() { // API documentation: Service#create |
| var ended = false; |
| return function myRPCImpl(method, requestData, callback) { |
| if (ended) |
| return; |
| if (!requestData) { |
| ended = true; |
| return; |
| } |
| // in a real-world scenario, the client would now send requestData to a server using some |
| // sort of transport layer (i.e. http), wait for responseData and call the callback. |
| performRequestOverTransportChannel(requestData, function(responseData) { |
| callback(null, responseData); |
| }); |
| }; |
| })(), /* requestDelimited? */ true, /* responseDelimited? */ true); |
| |
| // examplary server-side code for the sake of this example |
| function performRequestOverTransportChannel(requestData, callback) { |
| setTimeout(/* simulated delay */function() { |
| // 1. server decodes the request |
| var request = Hello.decodeDelimited(requestData); |
| // 2. server handles the request and creates a response |
| var response = { message: "Hello " + request.name }; |
| setTimeout(/* simulated delay */function() { |
| // 3. server encodes and sends the response |
| callback(World.encodeDelimited(response).finish()); |
| }, Math.random() * 250); |
| }, Math.random() * 250); |
| } |
| |
| // Listen for events: |
| |
| greeter.on("data", function(response, method) { |
| console.log("data in " + method.name + ":", response.message); |
| }); |
| |
| greeter.on("end", function() { |
| console.log("end"); |
| }); |
| |
| greeter.on("error", function(err, method) { |
| console.log("error in " + method.name + ":", err); |
| }); |
| |
| // Call methods: |
| |
| greeter.sayHello({ name: "one" }); |
| greeter.sayHello(Hello.create({ name: "two" })); // or use runtime messages |
| |
| // Listen to and emit your own events if you like: |
| |
| greeter.on("status", function(code, text) { |
| console.log("custom status:", code, text); |
| }); |
| |
| greeter.emit("status", 200, "OK"); |
| |
| // And, if applicable, end the service when you are done: |
| |
| setTimeout(function() { |
| greeter.end(); |
| // ^ Signals rpcImpl that the service has been ended client-side by calling it with a null buffer. |
| // Likewise, rpcImpl can also end the stream by calling its callback with an explicit null buffer. |
| greeter.sayHello({ name: "three" }, function(err) { |
| console.error("this should fail: " + err.message); |
| }); |
| }, 501); |