instructure / ic-ajax

ember-friendly jQuery.ajax wrapper
MIT License
167 stars 29 forks source link

jsonp #7

Open ulisesrmzroche opened 10 years ago

ulisesrmzroche commented 10 years ago

I'm having trouble when hitting an endpoint that uses jsonp. (tumblr, in my case). Same Origin is telling me though shall not pass, though.

This works

  var url = api_endpoint + '&callback=?'
  return $.getJSON(url).then(function(payload){
    return payload;
  })

But this doesn't

  var url = api_endpoint + '&callback=?'
  return ic.ajax.raw(this.get('endpoint')).then(function(payload){
     return payload
   });
nathanhammond commented 10 years ago

ic-ajax is a thin wrapper around $.ajax. If you're trying to implement JSONP on top of ic-ajax you'll need to pay close attention to these lines: https://github.com/instructure/ic-ajax/blob/master/lib/main.js#L86-L102

An untested, coding inside GitHub's comment editor version follows:

ic.ajax.raw(url, { dataType: 'jsonp', jsonpCallback: 'callbackName' });

Note that this will not play nicely with Ember's run loop by default. You'll need to do some more shenanigans to make that work.

@fivetanley @rpflorence This issue can be closed.

bguiz commented 10 years ago

Note that this will not play nicely with Ember's run loop by default. You'll need to do some more shenanigans to make that work.

@nathanhammond What are these shenanigans? If I console log the the output in the first (resolve) callback on req.then(), I get the expected output. However, the template bound to the property does not show this, and instead:

{
"_id": 101,
"_subscribers": []
}

How did you get around this in the run loop?

nathanhammond commented 10 years ago

@bguiz

  1. You'll need to wrap the body of the function in Ember.run(); to put it into the run loop.
  2. You'll possibly need to look the underlying objects up from the App container. Yes, this means .__container, which you're not supposed to do. (You could also register/inject a handle that will return you access to a particular thing.)
  3. You'll need to call Ember.set and Ember.get with the full method signature in order to properly update the object properties that you're setting.

Most of this is because the JSONP callback will be running in a global scope asynchronously.

bguiz commented 10 years ago

@nathanhammond Eeek that sounds like quite the hack. Could you post an example of that in a gist perhaps? ... I know what to do for points #1 and

3, but have the foggiest for point #2.

On 13 July 2014 02:13, Nathan Hammond notifications@github.com wrote:

@bguiz https://github.com/bguiz

  1. You'll need to wrap the body of the function in Ember.run(); to put it into the run loop.
  2. You'll possibly need to look the underlying objects up from the App container. Yes, this means .__container, which you're not supposed to do. (You could also register/inject a handle that will return you access to a particular thing.)
  3. You'll need to call Ember.set and Ember.get with the full method signature in order to properly update the object properties that you're setting.

Most of this is because the JSONP callback will be running in a global scope asynchronously.

— Reply to this email directly or view it on GitHub https://github.com/instructure/ic-ajax/issues/7#issuecomment-48816462.

nathanhammond commented 10 years ago

For example, in the callback:

var object = App.__container.lookup('controller:login');
Ember.set(object, 'property', value);

That should get you the Ember object that you need to set properties on, set it, and wrapped in a run loop it should all work out!

WARNING: Code is untested, and written in the comment editor without checking method signatures.

bguiz commented 10 years ago

@nathanhammond Thanks for that. Did not quite get it working for me. Hope that ic-ajax fixes this, and provides a usable way to use jsonp.

fivetanley commented 10 years ago

What about something like...

var promise = new Ember.RSVP.Promise(function(resolve, reject){
  ic.ajax.raw(url, { dataType: 'jsonp', jsonpCallback: 'callbackName' }).then(function(results){
    Ember.run(null, resolve, results);
  });
});

It should be noted that ic-ajax isn't really needed unless you want the fixture data stubbing. Since 1.3 ember-testing has been able to observe jQuery ajax requests and stop tests until they all finish. For all other promises, you shouldn't get errors if you upgrade to 1.6 you'll get test-friendly promises that are auto wrapped in the run loop: http://emberjs.com/blog/2014/07/07/ember-1-6-0-and-ember-1-7-0-beta-released.html

In the mean time, I'm not sure that the library will be maintained to update it in the mean time. You usually should not have any problems upgrading ember as we follow semver. I don't work at instructure anymore and have started using Trek's pretender library for ajax stubbing in my day job. Don't have much time to work on this or have permission to merge pull requests anymore.