-
Notifications
You must be signed in to change notification settings - Fork 75
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
feature request: async derived properties #117
Comments
Can you elaborate a bit more? Perhaps include some code for how you wish it worked? |
You bet: …
derived: {
// current behavior
mySyncProperty: {
deps: ['aProp']
, fn: function deriveMySyncProperty(){
return this.aProp + 1 // mySyncProperty now set
}
}
// proposed async behavior
, myAsyncProperty: {
deps: ['aProp']
, fn: _.debounce(function deriveMyAsyncProperty(done){
expensiveComputation(this.aProp, function(err, res){
if (err) done(err)
else done(null, res) // myAsyncProperty now set to res
})
}, 500)
}
}
… |
To chime in, I've found myself wanting to this for ajax calls: drivingDistance: {
deps: ['latitude', 'longitude'],
fn: function (done) {
fetchDrivingDistance(this.latitude + ',' + this.longitude, function (err, result) {
// done could be error first
done(err, result);
// or just accept a value
done(err ? 'Could not get driving distance' : 'Driving distance is ' + result);
});
}
} This isn't too hard to achieve otherwise with some listeners and a session property, but I do like the idea of the syntax above. |
Typically, with normal derived properties, everything happens synchronously. So we fire a You could fire a late |
I would vote "yes" for a second |
I think they should fire I like the idea and the proposed syntax, but I'm closer to +0 on this since it could have some quirks like that. |
You can achieve this same type of behavior by setting the result of your async function as a In some ways I think doing that would be preferable, albeit a bit more verbose. But doing so means we can also cleanly handle how to deal with the fact that derived properties can derive from each other. It also allows you to easily manage your own cache of the results, since the result is simply set as session property and control how often your expensive operation occurs. I'm hesitant to introduce this additional complexity to derived properties, they're not so simple as is :) I'd say something like this would suffice: session: {
drivingDistance: 'string'
},
calculateDrivingDistance: function () {
var self = this;
fetchDrivingDistance(this.latitude + ',' + this.longitude, function (err, result) {
self.drivingDistance = result;
});
} |
i think i'm going to close this for now. Thanks for the suggestion, though @joeybaker. Re-open if you disagree. |
@HenrikJoreteg the only downside with the current approach is that you have to manually add change even listeners to run the |
Yeah, that's fair. I'll leave it open for discussion. |
How would it deal with the fact that you'd still get |
IMHO, leaving |
Could you combine the session & derived approaches to avoid manually setting up listeners? e.g. session: {
drivingDistance: 'string'
},
derived: {
_drivingDistance: {
deps: ['latitude', 'longitude'],
fn: function () {
var self = this
fetchDrivingDistance(this.latitude + ',' + this.longitude, function (err, result) {
if (result) {
self.drivingDistance = result;
}
});
}
}
} Yes, it's kindof ugly that there's an extra Assuming it does, it would be cool to see an derived: {
drivingDistance: {
deps: ['latitude', 'longitude'],
async: true,
fn: function () {
var self = this
fetchDrivingDistance(this.latitude + ',' + this.longitude, function (err, result) {
// or maybe use the done(result) callback approach to make sure the right property is set
if (result) {
self.drivingDistance = result;
}
});
}
}
} Or maybe async properties like this could be their own thing, similar to derived properties but labeled |
I like @chesles suggestion of a |
This is actually pretty trivial to support: https://github.com/chesles/ampersand-state/compare/117-async-derived-properties |
I think fetching additional or related data is a common enough use case that might simplify doing model relationships. My main concern here is the edges surrounding this. For example every read of the derived prop before successful completion would cause a re-running of that async function running unless we also did that book keeping. |
You're right - had a few more edges to cover here to do this right. The initial implementation would call the async function multiple times without the Did a little refactor so there's an |
Added a few more tests and tweaked the bookkeeping so that:
Accessing the property while the async function runs just returns the previous value (or undefined), which I don't think is a problem. We could set the value to Check out my branch if you're interested in this feature and let me know if you see any issues. If you like it I can submit a PR. |
This looks good and seems fairly straight forward to merge with my PR for dataTypes and other enhancements to derived properties in #116 (type, default, and init). Also just to share a really hacky way of solving this problem using custom events:
|
I'd like this feature too. 👍 |
I'd really like to see this feature, but I've got a concern about the implementation in https://github.com/chesles/ampersand-state/commit/1688650daa164e9328b0220c999ed829fcdb74ae. By making sure the update function is only called once, don't you end up with a result that might not match its trigger? In other words, let's say I change a property |
Hey guys, did anything come of this? I was faced with this issue yesterday and ended up returning a promise from the derived |
I don't think we're ready to throw promises into the mix here. So far nobody has come up w/ a method that they feel is ready enough to make a PR for, it appears. |
agreed.
a key question that would still require bottoming out on. not that it's pertinent, but i can see folks abusing this, embedding application logic within the state obj itself. im not saying it's so, but there's something fishy feeling (to me*) about tying your application and model logic into the state container itself. just food for thought. |
So? What about async derived props? Maybe use promises as returns? |
It would be great if it was possible to derive properties in an async way. The
fn
could accept a callback that called if the function returnsundefined
.Use cases: debouncing derived properties, ajax calls, etc…
The text was updated successfully, but these errors were encountered: