Ultimately, the problem was really one of documentation. JSONP (or JSON with Padding) is mentioned in the $resource API; but, it's really only documented well in the $http API, which I have yet to dig into.
When I converted the $resource from a GET request to a JSONP request, I started off by simply switching the method to "JSONP". Coming from a jQuery background, I assumed that the "callback" parameter would get automatically generated and applied to the outgoing request. But, it did not.
Then, I tried adding an explicit "callback" parameter to the JSONP request configuration. But, this still didn't work. The network activity looked right; but, AngularJS was rejecting the request with an error.
Finally, I jumped over to the $http documentation and figured out where I was going wrong. Not only do I have to explicitly define my "callback" parameter in AngularJS, the callback parameter has to have the set value, "JSON_CALLBACK". Once I added this to the outgoing request configuration, the JSONP request started working.
It's an interesting approach. AngularJS looks at the outgoing URL and replaces the phrase "JSON_CALLBACK" with an auto-generated callback name. If you make the same JSONP request a few times in a row, you'll notice that the callback name increments in the URL:
As you can see, AngularJS generates functions that are accessible off the global angular namespace.
To pull this post together, I put together a simple little demo that makes a JSONP request for a list of friends and then renders the list on the page:
As you can see, the $resource instance is defined with the default parameter, callback: "JSON_CALLBACK". I'm then binding to the underlying $promise object of the response which will be resolved when the JSONP callback is invoked.
NOTE: jQuery seems to be able to access the proper status code in Firefox. As such, I assume the issue is one of cross-browser normalization? Or maybe a bug in AngularJS? I'm not sure.
Ultimately, I probably shouldn't use the $resource service with a JSONP request. $resource provided a level of abstraction that doesn't really add much value with the limited functionality of a JSONP request. I used it primarily because it was already in place; and, because I'm not super familiar with the underlying $http service... yet.
Want to use code from this post? Check out the license.