npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

honeyloops

v0.3.0

Published

Micro batching and scheduling over animation frames.

Downloads

4

Readme

Honeyloops

Honeyloops is a micro library (less than 512 bytes gzipped) for batching and scheduling the execution of handlers on frame rendering. It falls back to timeouts on older browsers, and has no external dependencies.

  1. Quick start
  2. Usage guide
  3. API reference
  4. Building and testing
  5. Compatibility
  6. Roadmap
  7. Changelog
  8. License

Quick start

Include honeyloops.js or honeyloops.min.js in your page, or require('honeyloops') when on node.js, and decorate the handlers that you want to be batched:

var render = Honeyloops.batch(function(){
    $container.css({ ... });
});

...and done. What you get back is a promise of executing the handler during the next frame redraw, just once per frame.

You can now call render whenever you need, how many times you want, just like before – but it will only be executed once, batched along all your other handlers, during the next frame.

Call a handler directly, attach it directly to multiple DOM listeners, change events, pass it around, it doesn't matter.

Usage guide

You can see Honeyloops as a central, globally available scheduler, so its usefulness shows when batching multiple handlers from various sources, as you can maintain a simple, decoupled architecture, while being sure that runs will be controlled.

var renderNotifications = Honeyloops.batch(function(){
    // Process only a small chunk per frame.
    var nn = notifications.consume(5);
    if (nn.length) {
        views = nn.map(renderNotification);
        $notifications.append(views);
        // We may have more.
        renderNotifications();
    }
});

notifications.on('receive', renderNotifications);

If you just fan out from a single entry point (ie. a DOM listener), you may want to batch it directly:

window.onscroll = Honeyloops.batch(function(event){
    updateBackground();
    updateNavbar();
});

You may call handlers during a run, and they will be scheduled on the next frame. For example, this is how you would accomplish a classic draw loop:

var draw = Honeyloops.batch(function(elapsed){
    // Paint your things, in order, scaled to time slice.
    if (isRunning)
        draw(); // Draw again on next frame.
});

var isRunning = false;
function start() { isRunning = true; draw() }
function stop()  { isRunning = false }

Though if you only have a single handler you may still want to write your own loop using requestAnimationFrame directly.

You can of course mix and match:

var updateCounter = Honeyloops.batch(function(value, prev){
    $counter.text(value);
    inflation += value - prev;
    inflateAnimation();
});

var inflateAnimation = Honeyloops.batch(function(elapsed){
    inflation = Math.max( 0.0, inflation - scale(deflation, elapsed) );
    $counter.css('transform', 'scale('+(1+inflation)+')');
    if (inflation > 0) inflateAnimation();
});

Many draw loops have to run each frame, but frames won't be requested until they are needed. You can keep this advantage by invoking handlers only when there, and architecting your code using a consumer approach.

API reference

Honeyloops publishes a single namespace, Honeyloops, either on window or as module.exports for commonjs-style environments.

Honeyloops.schedule

Honeyloops.schedule( function handler(ms elapsed) )

Schedules the execution of the given handler before the next animation frame. Handlers will be batched so they are executed together, and debounced so that each handler will only run once.

The handler will be passed the time elapsed since the last frame. If the handler is called again during a run, it will be scheduled for the next batch.

Scheduling a handler will replaces all previous schedules for this handler or any other handler with the same tag. See the documentation for tag below on how to group different handlers together.

Honeyloops.batch

Honeyloops.batch( function handler(any args..., ms elapsed), [any context] ) -> function

Wraps the given handler into a promise of executing the handler only once during the next frame. You can optionally pass a context for binding.

Any argument given to the wrapper will be passed to the wrapped function, with the time elapsed since last frame as the last argument. If the handler is called again during a run, it will be scheduled for the next batch.

Scheduling a handler will replaces all previous schedules for this handler or any other handler with the same tag. See the documentation for tag below on how to group different handlers together. Note that you should tag handlers before passing them to batch().

Honeyloops.tag

Honeyloops.tag( function handler, [scalar tag] ) -> uid

Returns the unique id distinguishing a handler. Identical handlers will always return the same id.

If given a custom tag, it will replace that handler's original tag, putting it in the same debouncing bucket as other handlers with the same tag.

var uid = Honeyloops.tag(myHandler);
Honeyloops.tag(myOtherHandler, uid);
Honeyloops.tag(yetAnotherHandler, uid);

Building and testing

You can run the automated test suite:

$ npm test

And build a minificated version of the source:

$ npm run build

More tasks are available on the Makefile:

lint: lints the source
spec: runs the test specs
coverage: runs the code coverage test
test: lint, spec and coverage threshold test
build: builds the minified version

Compatibility

Honeyloops falls back to setTimeout for environments which do not have requestAnimationFrame. While there are differences (which are detailed in the source for the shim) they are abstracted away. Note, though, that the fallback scheduler will run at half speed.

Roadmap

  • Helpers for looping
  • Helpers for dirty checking
  • Time scaling / priority
  • Dependency ordering
  • Profiling of handlers or main loop
  • Things like lastFrameTime available on Honeyloops
  • Before-frame/after-frame hooks
  • Queue/consumer-style helpers

Changelog

next

  • BREAKING: Scheduling a handler now replaces its previous schedules.
  • Published more methods on the public interface.
  • Added lints, specs and coverage tests.

v0.2.1

  • Honeyloops is now a proper NPM package.

Full changelog

License

The MIT License (MIT)

Copyright (c) 2013-2014, zenoamaro [email protected]

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.