Robert Mosolgo

To my knowledge, batman.js is not maintained. For that reason, I don't suggest that you use it for a new project!

Prevent and allowAndFire for asynchronous operations on a Batman.Set

Batman.js’s prevent and allowAndFire make it easy to fire a callback when you’re finished working on the members of a Batman.Set.

The Problem

Let’s say you have Batman.Set (or Batman.AssociationSet, or even a plain JS array) whose members are Batman.Model instances. You have a saveAll function that saves all the members:

class ThingsController extends Batman.Controller
  saveAll: (setOfRecords) ->
    setOfRecords.forEach (record) -> record.save()

But what if you wanted to call a callback when the whole operation was finished?

The Solution

  • Set up a listener on the "finished" event. Use once to avoid observer bloat.
  • Before each save operation, prevent "finished"
  • When each one finishes, allowAndFire "finished".

That way, it will get prevented n times – once for each item in the set – and it will finally be fired when the last operation is finished.

Here it is, all together:

class ThingsController extends Batman.Controller
  saveAll: (setOfRecords, callback) ->
    # observer:
    @once 'finished', ->
      callback()

    setOfRecords.forEach (record) => # mind the fat arrows!

      @prevent('finished')

      record.save (err, record) =>
        @allowAndFire('finished')

Note: @prevent and @allowAndFire are provided by Batman.EventEmitter, so it will only work with objects which have that mixin. Don’t worry – every object in batman.js is an event emitter! But plain JS objects are not.