Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions docs/core/utils.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,22 @@ AFRAME.registerComponent('foo', {
});
```

### `AFRAME.utils.throttleLeadingAndTrailing (function, minimumInterval [, optionalContext])`

[lodash]: https://lodash.com/docs/#throttle

Returns a throttled function that is called at most once every `minimumInterval` milliseconds, but ensures that the very last call of a burst gets deferred until the end of the interval. This is useful when an event is used to trigger synchronization of state, and there is a need to converge to the correct final state following a burst of events.

Example use cases:

* synchronizing state based on the componentchanged event
* following a mouse pointer using the mousemove event
* integrating with [THREE.TransformControls](https://threejs.org/docs/#examples/en/controls/TransformControls), via the objectChange event.

A context such as `this` can be provided to handle function binding for convenience.

The same as [lodash's`throttle`][lodash], with `leading` and `trailing` options both set to `true`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wonder if this reference is a liability long term in case lodash API changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe, but the existing docs already reference loadash throttle (the same link)

See: https://aframe.io/docs/1.3.0/core/utils.html#aframe-utils-throttle-function-minimuminterval-optionalcontext

This doesn't make the situation any worse, I think.


## Miscellaneous

### `AFRAME.utils.getUrlParameter (name)`
Expand Down
5 changes: 4 additions & 1 deletion src/core/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ var Component = module.exports.Component = function (el, attrValue, id) {
}

// Last value passed to updateProperties.
this.throttledEmitComponentChanged = utils.throttleComponentChanged(function emitChange () {
// This type of throttle ensures that when a burst of changes occurs, the final change to the
// component always triggers an event (so a consumer of this event will end up reading the correct
// final state, following a burst of changes).
this.throttledEmitComponentChanged = utils.throttleLeadingAndTrailing(function emitChange () {
el.emit('componentchanged', self.evtDetail, false);
}, 200);
this.updateProperties(attrValue);
Expand Down
17 changes: 15 additions & 2 deletions src/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,21 @@ module.exports.throttle = function (functionToThrottle, minimumInterval, optiona
* Returns throttle function that gets called at most once every interval.
* If there are multiple calls in the last interval we call the function one additional
* time.
* It behaves like a throttle except for the very last call that gets deferred until the end of the interval.
* It behaves like throttle except for the very last call that gets deferred until the end of the interval.
* This is useful when an event is used to trigger synchronization of state, and there is a need to converge
* to the correct final state following a burst of events.
*
* Example use cases:
* - synchronizing state based on the componentchanged event
* - following a mouse pointer using the mousemove event
* - integrating with THREE.TransformControls, via the objectChange event.
*
* @param {function} functionToThrottle
* @param {number} minimumInterval - Minimal interval between calls (milliseconds).
* @param {object} optionalContext - If given, bind function to throttle to this context.
* @returns {function} Throttled function.
*/
module.exports.throttleComponentChanged = function (functionToThrottle, minimumInterval, optionalContext) {
module.exports.throttleLeadingAndTrailing = function (functionToThrottle, minimumInterval, optionalContext) {
var lastTime;
var deferTimer;
if (optionalContext) {
Expand All @@ -99,6 +106,12 @@ module.exports.throttleComponentChanged = function (functionToThrottle, minimumI
};
};

/**
* Identical to throttleLeadingAndTrailing.
* Exists for back-compatibility with 1.3.0.
*/
module.exports.throttleComponentChanged = module.exports.throttleLeadingAndTrailing;
Copy link
Member

@dmarcos dmarcos Nov 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can just rename. Don't think many were relying on this. We can add a deprecation in next release notes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK - removed this. What needs to happen to make sure this gets tracked for the release note?


/**
* Returns throttle function that gets called at most once every interval.
* Uses the time/timeDelta timestamps provided by the global render loop for better perf.
Expand Down