Knockout catching errors

http://brianmhunt.github.io/articles/knockout-catching-errors/

by bmh_ca

HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.0.0/knockout-min.js"></script>
<div id='X'>
    <h1>Sample of errors</h1>
    <h2>A binding that does not exist</h2>
    <div data-bind='doesnotexist: obs'></div>
    <h2>A binding init throws an error</h2>
    <div data-bind='throws: obs'></div>
    <h2>When no error occurs</h2>
    <div data-bind='text: obs'></div>
</div>

CSS

/* [data-bind] */.binding-error {
  border: 4px dashed red;
  background-color: #F88;
}

/* [data-bind] */.binding-error:after {
  font-size: 16px;
  color: red;
  background-color: white;
  padding: 2px 0.5em;
  border: 1px solid gray;
  font-style: italic;
  content: "This item may not be working as expected.";
}

CoffeeScript

ErrorHandlingBindingProvider = ->
  # The original binding handler still does the real work; you
  # can use your own or an alternative such as knockout-secure-binding
  # here though.
  orig = new ko.bindingProvider()

  # We also pass through the `nodeHasBindings` call.
  @nodeHasBindings = orig.nodeHasBindings

  # This returns a map of binding names to respective handlers, given a node
  # and the bindingContext.
  @getBindings = (node, bindingContext) ->
    try
      # The bindings_map will be `null` if there are no bindings, otherwise
      # an object mapping { name: binding }.
      bindings_map = orig.getBindings(node, bindingContext)
    catch err
      # When there is an error, throw out some useful context.
      console.error("Binding error: ", err.message, "\nNode:", node,
        "\nContext:", ko.contextFor(node))
      $(node).addClass("binding-error")

    # Pass null straight up.
    if bindings_map == null then return null

    # If there isn't at least one good binding, print some helpful
    # debugging information.
    unless _(bindings_map).keys().any((m) -> _.has(ko.bindingHandlers, m))
      console.error("No bindings found:", bindings_map, "Node:", node)
      $(node).addClass("binding-error")
      return null

    return bindings_map
  return

# Replace the default Knockout binding provider.
ko.bindingProvider.instance = new ErrorHandlingBindingProvider()

# The `isolate_call` function wraps `binding.init` and `binding.update`
isolate_call = (binding, fn_name, key) ->
  # binding is the binding object
  # fn_name is one of `init` or `update`
  # key is the name of the binding

  fn = binding[fn_name]
  unless fn then return undefined

  unless _.isFunction(fn)
    console.error("%cERROR%c Binding #{key}.#{fn_name} is not a function",
      "color:red", "color:black", binding, fn_name, fn)
    return undefined

  wrapped_fn = (args...) ->
    try
      # Pass-through the call to the original handler.
      return fn.apply(binding,...