Coder Social home page Coder Social logo

stack.js's Introduction

stack.js

Pseudo-call stack creation for managing method execution order.

Basically, this means you can define a set of methods to run in sequence with slightly more control of when methods get run within the context of a current code block. The big takeaways are:

  • Being able to defer methods in a another "call stack" from the current code context
  • Preventing unhandled errors in the current context blocking additional, sequential method invocations

Everything is still being executed in a single JavaScript call stack, but this code will sit at the top of stack and manage sub stacks you can set up with methods like defer(). In the process, it will catch unhandled errors for you so that additional call stacks (these sub stacks) can be executed without being interrupted by those exceptions.

Usage

See how defer() is used to execute a method after the current (Stack-based) call stack, started with exec(), has finished. (invoked() is also used to call functions in Stack-based call stacks as seen later on.)

function hardWork(){
  console.log("Hard work");
}

function work(){
  Stack.defer(hardWork); // delays call of hardWork() in another call stack
  console.log("Easy work");
}

Stack.exec(work); // execute work() in a managed call stack
// output:
// Easy work
// Hard work

Here you can see how throwing unhandled errors does not affect the deferred calls.

function hardWork(){
  console.log("Hard work");
}

function work(){
  Stack.defer(hardWork); // delays call of hardWork()
  console.log("Easy work");
  throw new Error("Getting tired"); // won't affect hardWork being in other call stack
}

Stack.exec(work); // execute work() in a managed call stack
// output:
// Easy work
// Error: Getting tired
// Hard work

The method invoked() allows you to bind functions to a call stack when called. Also, here you see additional options for specifying methods in the Stack API.

function clickHandler(event){
  // defer log() called for console object with arguments: event.target.localName
  Stack.defer(console, console.log, [event.target.localName]);
  console.log("clicked:");
}

document.addEventListener("click", Stack.invoked(clickHandler)); // clickHandler called in stack
// output on click:
// clicked:
// html

You can also build up a list of call stacks using push(). This also demonstrates different ways to specify stack calls.

function first(){
  console.log("first");
}
function second(){
  console.log("second");
}
function third(){
  console.log("third");
}

Stack.push(first);
Stack.push(this, second);
Stack.push(this, "third");
Stack.exec();
// outputs:
// first
// second
// third

API

Stack JS introduces a global Stack object from which all Stack methods are called. Methods provided to the Stack API represent the roots to Stack-managed call stacks. When called, they execute all code specific to their call stack context. Unhandled errors in those calls will only affect code within their own contexts and not those of other call stacks.

The API accepts methods both with and without a scope as well as with and without an arguments list. When a scope is provided, the method can be a function reference or the name of the method as it is defined within the scope object. There are usually two method signatures that allow this:

  • member([method [, argumentsArray]])
  • member([scope, method [, argumentsArray]])

When the first parameter is specified as a function, the first signature is used. Otherwise, the second is used, with the first parameter representing the scope with which to call the function. The arguments array will be passed into the method function when it is called. If the method is invoked with other arguments, those arguments will be provided first, followed by the arguments specified here in the arguments array.

exec

  • Stack.exec([method [, argumentsArray]])
  • Stack.exec([scope, method [, argumentsArray]])

Starts executing the set of call stack methods currently defined in the stack. If a method is passed into exec(), it will be pushed onto the end of the stack list.

Once exec() completes executing all methods in a stack list, the list is cleared.

push

  • Stack.push([method [, argumentsArray]])
  • Stack.push([scope, method [, argumentsArray]])

Adds a method to the stack list. This method will be called the next time exec() is run. The order of execution occurs in the order in which methods are pushed onto the stack list. However, using the defer() method will allow stack methods to be called directly after the current call stack rather than being added to the end.

pushOnce

  • Stack.pushOnce([method [, argumentsArray]])
  • Stack.pushOnce([scope, method [, argumentsArray]])

Like push() but does not allow duplication when pushing methods. In additional calls to pushOnce() with the same method, the previous is found and removed from the stack list. Duplicate methods are found by function reference only; the argument list is ignored.

defer

  • Stack.defer([method [, argumentsArray]])
  • Stack.defer([scope, method [, argumentsArray]])

Sets a method to be called in the next call stack immediately following the current call stack. Becaise of this, defer() can only be called in the context of a Stack-managed call stack. To add methods to the call stack list outside of a Stack-managed call stack, use push().

deferOnce

  • Stack.deferOnce([method [, argumentsArray]])
  • Stack.deferOnce([scope, method [, argumentsArray]])

Like defer() but does not allow duplication when deferring methods. In additional calls to deferOnce() with the same method, the previous is found and removed from the stack list. Duplicate methods are found by function reference only; the argument list is ignored.

invoked

  • Stack.invoked([method [, argumentsArray]])
  • Stack.invoked([scope, method [, argumentsArray]])

Creates a new function that wraps the provided method in a wrapper that causes the method to be called in the context of a new call stack. In other words, when the generated method is called, it will effectively call exec() with the method. This is useful for generating methods for event handlers that will force those event handlers to be called in a Stack-managed call stack.

value

Stack.value()

Returns the value returned by the method call within the previous call stack. A single deferred method, for example, could get the value in the return statement in the previous call stack by calling value().

kill

Stack.kill()

Stops execution of any additional call stacks within the stack list, clearing the stack list in the process. The current stack will complete as expected, but additional stacks, even those added after the call to kill(), will not.

clear

Stack.clear()

Removes all call stacks from the stack list. This will also clear the value returned by value() as well as reset exec() (nested exec() calls are ignored, though it is possible to error out of an exec() run by throwing an error in a custom onerror handler at which point a call to clear() is needed to reset exec()).

onerror (event)

Stack.onerror = function(error)

Callback handler for unhandled errors encountered in call stacks. A default handler is provided that will output errors to the console, but that can be overridden by defining your own in the onerror property.

onerror handlers accept one argument: the error thrown by the unhandled exception.

stack.js's People

Contributors

senocular avatar

Stargazers

Antonio Brandao avatar frankwinter avatar

Watchers

James Cloos avatar  avatar

stack.js's Issues

readme could use a better example

I read the readme and don't know why this model would be something I would want to switch to. I get the gist that it's for maintaining a particular execution order when you have functions of varying runtime complexity, but I don't see why stack.js is better than my alternative choices. (I'm not really sure what the alternative(s) would be… how about a comparison?)

I believe that stack.js has a place in the world, but I'm too dumb to understand its place from the readme so far. ❓

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.