Closed albertosantini closed 8 years ago
I like the API as you describe it so far. What do you think about using promises instead of callback.
rio.E({
entrypoint: "echo",
data: myData
})
.then(function(data) {
console.log(data);
})
.catch(function(error) {
console.log(error);
});
Very tempting. :)
One main advantage it would be a better error handling.
Anyway I prefer a base and minimal approach, using callbacks: they are a fundamental building block, letting the user how to handle the async flow.
Finally the user can use a promisification step.
See, for instance, bluebird promisification.
I would not add complexity, choosing an opinionated Promises library, or another abstract layer: rio vision aims to simplicity and lightweight.
Alias is rio.e(params) { ...
due to eslint new-cap
rule, a function with a name starting with an uppercase letter should only be used as a constructor.
I prefer not to disable it.
Sorry if this is the wrong place to ask. I tried to promisify rio.evaluate with bluebird, but it doesnMt work, because bluebird expects the callback as the last argument, whereas rio.evaluate's callback is an option in the options hash. Many API's have the options as an intermediate argument and the callback as the last one. This would be nice in terms of unification, while keeping callback style.
Nice point! :)
After changing my working directory
function evaluate(params, callback) {
var cmd = params.command || "",
filename = params.filename || "",
entrypoint = params.entrypoint || "",
cb = params.callback || callback,
options = params;
options.callback = cb;
...
// TODO: fix default callback in sendAction
I tried
var Promise = require("bluebird");
var rio = Promise.promisifyAll(require("../lib/rio"));
rio.eAsync({command: "pi / 2 * 2"}).then(function(res) {console.log(res)});
// => 3.14...
@tamaracha would be enough for your use cases?
Nice, yet another way :-)
I solved it myself by manually promisifying rio.evaluate:
var rio=require("rio");
rio.evaluateAsync=function(command,options){
return new Promise(function(resolve,reject){
if(!options){var options={};}
options.callback=function(err,result){
if(err){return reject(err);}
return resolve(result);
};
return rio.evaluate(command,options);
});
};
Now, in express, I can do something like:
return rio.evaluateAsync(req.params.rio)
.then(function(data){
return res.send(data.toString()); // or whatever
},function(e){
return res.sendStatus(500);
});
I'm comfortable now, thanks for the quick reply.
Ok. I take a step away from the change.
Thanks about the snippet.
I will add the example code in the README in the section Promisifying
. :)
@tamaracha A few months ago... https://github.com/albertosantini/node-rio/commit/34d517597e28de8553b89aaa94f454f7f13676a5
dev-2.x
branch merged.
The proposal is the unification of the evaluation APIs into one.
AS IS
function evaluate(cmd, options) { ...
function sourceAndEval(filename, options) {...
function bufferAndEval(buffer, options) { ...
TO BE
Signature:
function evaluate(params) { ...
Default params:
Alias:
function E(params) { ...
Notes
params
be a simplestring
? Just to use it quickly asrio.E("2+2")
instead ofrio.E({command: "2+2"})
command
orcmd
? I prefercommand
and I would resolve params also as a string.entrypoint
. It is a surrogate forcommand
. However the following use case proves his need:It is a convenient way to append something after the command, especially the stringify of data.
Constraints
command
ORfilename
ORentrypoint
need to be filled. Otherwise it is missing the evaluation object.command
ANDfilename
ANDentrypoint
are empty then error. As above, said in different way.command
ANDfilename
are exclusive: if both are not empty then error. Otherwise what does rio evaluate, command or filename?command
ANDfilename
are empty thenentrypoint
is mandatory. This is the case when rio evaluates a function defined on R side.host
ANDpath
are exclusive. rio needs to choose beetween net socket or unix socket.Use Cases
Snippets extracted from the examples.