Search code examples
voltrb

What does the exception "ArgumentError: a promise has already been chained" mean, and how do I debug it?


I'm going a little nuts working with Volt at the moment. The moment I try to do something a bit more complicated I end up getting the exception "ArgumentError: a promise has already been chained" in the browser console.

The stack trace doesn't point to anything I can interpret as useful.

That does this error actually mean, and how do I go about trying to track down the cause?

I'd post some code, but some of these errors appear on page load with no indication of where the problem is, so I'd need to post the entire app :/


Solution

  • Volt uses Opal's promise implementation, which I believe is based on the A+ spec in JS land. The error your seeing is because a promise can only have a single .then or .fail block on it. Each .then or .fail will return a new promise that you can then chain off of.

    So you can do this:

    promise = Promise.new
    promise2 = promise.then do
      ..
    end
    promise2.then do
      ..
    end
    

    (notice I'm assigning promise2 instead of chaining off of the first one again)

    But you can not do something like this:

    promise = Promise.new
    promise.then do
      ...
    end
    
    promise.then do
      ..
    end
    

    (Notice how I called .then on promise more than once)

    A more compact way to write the first is to chain off of the end's

    promise = Promise.new
    
    promise.then do
      ..
    end.then do
      ..
    end.fail do
      ..
    end
    

    Volt bindings expect a promise that hasn't been chained on. Also, I think I can make it work where you can chain multiple times, though I haven't thought through all of the implications of this, so I could be wrong. If I get some time I might write a new promise implementation that can handle this. If your still seeing that error and the above doesn't explain why its there, let me know. Thanks!