diff --git a/.npmignore b/.npmignore index 14f07ae8d..06e498a18 100644 --- a/.npmignore +++ b/.npmignore @@ -5,3 +5,4 @@ node_modules/ types/types.d.ts bench.txt docs/ +examples/ diff --git a/examples/streaming-rpc.js b/examples/streaming-rpc.js index edc6ddf85..80450bf01 100644 --- a/examples/streaming-rpc.js +++ b/examples/streaming-rpc.js @@ -1,5 +1,7 @@ var protobuf = require(".."); +// Load a definition with services: + var root = protobuf.Root.fromJSON({ nested: { Greeter: { @@ -31,35 +33,39 @@ var root = protobuf.Root.fromJSON({ } }); +// Get its types: + var Greeter = root.lookup("Greeter"), Hello = root.lookup("Hello"), World = root.lookup("World"); -var ended = false; +// Provide a stream-aware RPC implementation: -// Implement: Stream-aware RPC implementation -function rpcImpl(method, requestData, callback) { - if (ended) - return; - if (!requestData) { - console.log("rpc ended client-side."); - ended = true; - return; - } - setTimeout(function() { - try { - // - var hello = Hello.decodeDelimited(requestData); - var responseData = World.encodeDelimited({ message: 'Hello ' + hello.name + ' !' }).finish(); - // - callback(null, responseData); - } catch (err) { - callback(err); +var greeter = Greeter.create(/* rpcImpl */ (function() { // API documentation: Service#create + var ended = false; + return function myRPCImpl(method, requestData, callback) { + if (ended) + return; + if (!requestData) { + console.log("rpc ended client-side."); + ended = true; + return; } - }, Math.random() * 500); -} + setTimeout(function() { + try { + // begin exemplary server side code + var hello = Hello.decodeDelimited(requestData); + var responseData = World.encodeDelimited({ message: 'Hello ' + hello.name + ' !' }).finish(); + // end exemplary server side code + callback(null, responseData); + } catch (err) { + callback(err); + } + }, Math.random() * 500); + }; +})(), /* requestDelimited? */ true, /* responseDelimited? */ true); -var greeter = Greeter.create(rpcImpl, true, true); +// Listen for events: greeter.on("data", function(response, method) { console.log("data:", response.message); @@ -73,14 +79,25 @@ greeter.on("error", function(err, method) { console.log("error:", err); }); +// Call methods: + greeter.sayHello({ name: 'protocol' }); greeter.sayHello({ name: 'buffers' }); -greeter.sayHello({ name: 'for' }); +greeter.sayHello(Hello.create({ name: 'for' })); // or use runtime messages + +// Listen to and emit your own events if you want: + +greeter.on("status", function(code, text) { + console.log("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 end the stream by calling its callback with an explicit null buffer. + // Likewise, rpcImpl can also end the stream by calling its callback with an explicit null buffer. greeter.sayHello({ name: 'javascript' }); // does nothing }, 1000); diff --git a/src/service.js b/src/service.js index 49258a055..9361b0dbb 100644 --- a/src/service.js +++ b/src/service.js @@ -160,10 +160,11 @@ ServicePrototype.remove = function remove(object) { ServicePrototype.create = function create(rpcImpl, requestDelimited, responseDelimited) { var rpcService = new rpc.Service(rpcImpl); this.getMethodsArray().forEach(function(method) { - var lcName = method.name.substring(0, 1).toLowerCase() + method.name.substring(1); - rpcService[lcName] = function(request, callback) { + rpcService[method.name.substring(0, 1).toLowerCase() + method.name.substring(1)] = function callVirtual(request, /* optional */ callback) { if (!rpcService.$rpc) // already ended? return; + if (!request) + throw util._TypeError("request", "not null"); method.resolve(); var requestData; try {