New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Seneca actions and plugins do not support => functions. #194
Comments
this came up before in this issue, i was just making it more explicit: https://github.com/rjrodger/seneca/issues/150#issuecomment-137552687 |
a good article on these changes: arrow this |
👍 imo async callbacks should not have context. |
seneca actions are not lambdas, so nor are they callbacks - they are action definitions actions do indeed have context - the current seneca instance all that said, we should probably allow @AdrianRossouw signature as an option in 0.8, given that it makes I am open to further discussion on this |
This isn't a blocker, but just something we should also consider. ie: seneca.act('cmd=foo', (err, args) => {...} ) I think we're lucky there in that there is already a 'seneca' context available there, |
Maybe this will help someone, I've been suffering from process getting shutdown when some plugin performs this.add( {foo:'bar'}, function( args, done ) {
this.act( { role: 'another', cmd: 'cmd' } (err, res) => {
done("some error");
}
} Using arrow function causes the context of Converting to non lambda syntax fixed the whole thing. Thanks. |
Closing, this is a non-issue. If you want to use arrow functions you can in places where it makes sense, it doesn't make sense in actions, where we are calling it with seneca as 'use strict'
const Seneca = require('seneca')
const seneca = Seneca()
seneca.add({ cmd: 'test' }, function (args, callback) {
const fn = () => {
callback(null, { name: this.name })
}()
})
seneca.act({ cmd: 'test' }, function (err, result) {
console.assert(result.name === seneca.name)
}) |
I'm not so sure this should be so quickly dismissed. The failure of arrow functions to "work" is a side-effect of the design decision, which was to leverage the context object ( If it can be shown that the current design is necessary to the implementation of actions, then there needn't be further discussion. Certainly arrow functions don't make sense if your function has a context. But the question is, "should it?" It sucks to break an API, but if the API becomes problematic, what has to happen must happen. I don't suspect this issue will just go away. Maybe another issue should be created for this discussion, however. (Related, Mocha leverages context where it shouldn't. I think originally, the context was seen as a way to simplify writing tests, since it's not always used. But the price is loss of developer control, and confusion about what |
You know ... on reflection these are fair points. Even though @geek is correct - these are not lambdas, it doesn't mean people won't do it anyway - we should honour the principle of least surprise http://www.catb.org/esr/writings/taoup/html/ch11s01.html Re-opening to start discussion on a backwards compatible way to solve this issue - i.e. make possible the "natural" use of arrow functions. The key issue is that the context of each action call needs to be track so that you can trace the flow of messages. calls to @geek is it as simple as looking at the function signature?
|
We need some thinking on this functionality. All of the points above are valid but I would like to add as someone who is pulling stats out of Seneca that the end result of using context is still important. I'm just a little worried that we are going to change from this:
To this:
I get that lambda's are hot stuff but these are contextual functions. I don't know how great I feel about changing the signature to leverage a language feature which is being shoehorned in. I'm not convinced Perhaps the answer is both? If you don't need context you can use a lambda. This won't be available and any further requests you make will break the call chain. If you use a full function you gain context. I like this idea as it makes the usage of A lot of people may simply not be aware that you can track a 'transaction' through the system because of this functionality. |
I do think we should support changing the default behavior so that you can disable the binding seneca to the action. Thoughts on doing that, @rjrodger ? |
@geek But that's an all or nothing scenario.. Not fine grained enough for me. |
Given that something has to use actionFunction.call(context, args, callback); one could just: actionFunction(context, args, callback); Naming that first parameter For backwards compatibility, you could naively do this: if (actionFunction.length === 2) {
actionFunction.call(context, args, callback);
} else {
actionFunction(context, args, callback);
} mind you I'm not familiar with the implementation. |
@boneskull yup thats the crux of the issues. I,d he happy to see a solution similar to the above, sanity checked of course 😊 |
i've taken to passing the ctx as the first argument in my callbacks (ala python style), because it's consistent and it works. It also doesn't interfere with node's callback last style. I've seen some situation where the function.length can't be relied upon any more due to spread and rest operators btw. I think that if you are going to break the api, break it in a more future-safe direction at least. |
Sorry to do a lame question but this works: 'use strict'
const seneca = require('seneca')()
seneca.add({
cmd: 'another'
}, (msg, cb) => {
cb(null, {
response: 'hello'
})
})
seneca.add({
cmd: 'call'
}, (msg, cb) => {
msg.cmd = 'another'
seneca.act(msg, cb)
})
seneca.act({ cmd: 'call' }, console.log) In all examples in this thread, functions/lambda are defined in the same scope, so the seneca instance is available, even if In plugins it's even better, because the plugin factory function is called with However, I am obsessed with perf these days, and defining actions as anonymous function is bad because they will be hard to track. |
it works for seneca.act, but there are a few places the context is (mis?)used like with |
I think we are going again to |
they occur hundreds of times in the last codebase i worked on. With all the different instances of that app, they occur thousands of times. Many of the seneca-extensions also use them. |
how many actions have you got? they are like 10%, 20%? That app is huge :). The approach I am following is to understand the impact of not fixing it, given that the most common case BTW, I do not like passing seneca as Given that we are discussing this topic and we are speaking about breaking APIs, let me throw the other end of the spectrum: augmenting the incoming msg. seneca.add('a:b', (req, cb) => {
console.log(req.msg)
req.act('b:c', cb)
}) |
@mcollina I like the last example. I was thinking of a solution where we don't break the existing default behavior. Here is a proposal: Add This will allow context to be bound, as well as your last example @mcollina, which doesn't have Thoughts? |
i haven't checked back in a while, but I think that @mcollina 's last version is the best solution here. |
relates to #288 |
The way that we currently register callbacks with seneca is not forward compatible with ES6.
The problem is thus :
The only thing I can think of is to explicitly pass in the seneca instance as the first argument,
which would break the function signature and all existing seneca code :
The one trick that we could have used was checking arity with function.length, but I think that
becomes much less reliable with default and ...rest parameters, and would lead to strange and hard to debug errors.
The text was updated successfully, but these errors were encountered: