Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite transport #25

Closed
wants to merge 9 commits into from
Closed

Conversation

jharding
Copy link
Contributor

Looking for some feedback. This change would allow you to configure the ajax request so you could set headers, parse the response, etc. It should resolve #8, #13, #20.

My only concern is that this exposes too much. Rather than making every ajax option configurable, we could just whitelist the ones we think would be useful. Maybe exposing everything is the way to go though, after all who are we to deem which options are useful 😃.

rateLimitFn = (/^throttle$/i).test(o.rateLimitFn) ?
utils.throttle : utils.debounce;
maxConcurrentConnections = utils.isNumber(o.maxConcurrentConnections) ?
o.maxConcurrentConnections : maxConcurrentConnections || 6;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not just have '6' instead of 'maxConcurrentConnections || 6', I don't see how maxConcurrentConnections could be instantiated at this point?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maxConcurrentConnections is a static variable shared between each Transport instance. So if you have the following code:

$('.typeahead-one').typeahead({
  maxConcurrentConnections: 10
});

$('.typeahead-one').typeahead({
  maxConcurrentConnections: 4
});

The final value for maxConcurrentConnections should be 4.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aha, makes sense. I was considering the single transport case.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more thing we should discuss is if it makes sense to have the transports share a cache. Might make more sense to give each transport its own cache instance, reducing the coupling between the activity on the inputs.

@jharding
Copy link
Contributor Author

One more thing we should discuss is if it makes sense to have the transports share a cache. Might make more sense to give each transport its own cache instance, reducing the coupling between the activity on the inputs.

I could go either way on this. @timtrueman any thoughts?

@timtrueman
Copy link
Contributor

I'd do whatever is simplest, keeping in mind non-robots can only type into one input at a time and the likelihood of returning one you just used after switching to another seems low?

@jharding
Copy link
Contributor Author

The more I think I about it, the more I favor having a shared request cache. If we have a request cache per transport, then the number of potentially cached requests grows with the number of datasets. So if you had 10 datasets, we could potentially be caching 100 (or more) requests and that's just overkill.

Also, the browser will most likely be caching these requests so it's fine if we're aggressive in our cache eviction policy.

@timtrueman
Copy link
Contributor

Agreed. The core value of a request cache in my mind is for the delete key case.

@vskarich
Copy link
Collaborator

That sounds fair to me. I'm for leaving it as-is.

On Fri, Feb 22, 2013 at 12:00 AM, Jake Harding notifications@github.comwrote:

The more I think I about it, the more I favor having a shared request
cache. If we have a request cache per transport, then the number of
potentially cached requests grows with the number of datasets. So if you
had 10 datasets, we could potentially be caching 100 (or more) requests and
that's just overkill.

Also, the browser will most likely be caching these requests so it's fine
if we're aggressive in our cache eviction policy.


Reply to this email directly or view it on GitHubhttps://github.com//pull/25#issuecomment-13932592.

@jharding
Copy link
Contributor Author

I'll update RequestCache to be a singleton tomorrow.

@sullimander
Copy link

Looks good to me. I like the idea of opening all the options to ajax. The one option that might be problematic though is dataType, since the rest of the library is build on the assumption that the response is JSON. Maybe whitelist it to just json and jsonp. Also there is no default set for dataType.

@jharding
Copy link
Contributor Author

That's a good point, we should definitely whitelist json and jsonp.

@@ -53,29 +48,23 @@ var Transport = (function() {

url = url.replace(this.wildcard, encodeURIComponent(query || ''));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this is not being used in the ajax call anymore, which i'm guessing is wrong?
it should overwrite the ajaxSettings.url (or something along those lines)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, I'll make sure to address this.

@dogoku
Copy link

dogoku commented Feb 23, 2013

I actually like this approach a lot better than mine. Having a Transport for each Dataset seems to work great

@jharding
Copy link
Contributor Author

I'm questioning whether or not making every option configurable, it might be too overwhelming. Also, this wouldn't exactly expose a great way of processing responses before typeahead.js got a hold of it. You could use dataFilter, but since that gets passed the raw response, you'd have to parse it yourself. Also dataFilter wouldn't get called for jsonp requests since it's not a XHR.

As of right now, here's what I know we need to support:

  • jsonp
  • setting timeout
  • setting headers
  • turning off browser caching
  • response data filtering

If this is all we need to support, I say we add the following options:

  • dataType
  • timeout
  • beforeSend
  • cache
  • filter

The first 4 we would just pass along to jQuery.ajax, and the last one we would call immediately in the success callback.

Thoughts?


My proposal for the new API:

$('.typeahead').typeahead({
  name: 'states',
  limit: 5,
  template: '<p>{{value}} – United States of America</p>',
  engine: Hogan,
  local: ['Michigan', 'California'],
  prefetch: {
    url: '/states.json',
    ttl: 3600000,
    filter: function(resp) { /* parse suggestions out of response  */ }
  },
  remote: {
    url: '/states?q=%WILDCARD',
    wildcard: '%WILDCARD',
    rateLimitFn: 'throttle',
    rateLimitWait: 300, // rateLimitWait or wait? i think i prefer the former
    maxConcurrentConnections: 4,
    dataType: 'json',
    timeout: 2000,
    cache: true,
    beforeSend: function(jqXhr, settings) { /* set headers, etc. */ },
    filter: function(resp) { /* parse suggestions out of response  */ }
  }
});

@dogoku
Copy link

dogoku commented Feb 24, 2013

It's a shame dataFilter can't be used for jsonp

@jharding jharding mentioned this pull request Feb 26, 2013
@jharding
Copy link
Contributor Author

I am also thinking we should add a replace option to the remote object to handle issues like #20.

@jharding
Copy link
Contributor Author

I'm really happy with the changes I made. It doesn't complicate the simple use case and it allows for maximum configuration for the advanced use cases. The following APIs would be supported with this pull request:

Simple

$('.typeahead').typeahead({
  name: 'books',
  local: ['Watership Down', 'Player Piano'],
  prefetch: '/top_books.json',
  remote: 'books?q=%QUERY'
});

Advanced

$('.typeahead').typeahead({
  name: 'books',
  template: '<h2>{{value}}</h2>',
  engine: Hogan,
  local: ['Watership Down', 'Player Piano'],
  prefetch: {
    url: '/top_books.json',
    ttl: 60 * 60 * 1000,
    filter: function(data) { /* filter data */ }
  },
  remote: {
    name: 'books?q=%BOOK',
    wildcard: '%BOOK',
    replace: function(url, uriEncodedQuery) { 
      // if set, wildcard is ignored and this function handles
     // query subsitution
    },
    rateLimitFn: 'throttle',
    rateLimitWait: 200,
    maxParallelRequests: 6,
    dataType: 'json',
    timeout: 2000,
    cache: true,
    beforeSend: function(jqXhr, settings) { /* set headers, etc. */ },
    filter: function(resp) { /* parse suggestions out of response  */ }    
});

@timtrueman
Copy link
Contributor

I like it.

@vskarich
Copy link
Collaborator

+1

On Mon, Feb 25, 2013 at 10:38 PM, Tim Trueman notifications@github.comwrote:

I like it.


Reply to this email directly or view it on GitHubhttps://github.com//pull/25#issuecomment-14097939
.

@jharding jharding mentioned this pull request Mar 4, 2013
@jharding
Copy link
Contributor Author

jharding commented Mar 4, 2013

Merged into integration-0.9.0.

@jharding jharding closed this Mar 4, 2013
@stayce
Copy link

stayce commented Apr 10, 2013

Is JSONP supported? Can I make XHR request? Is there an example? Thanks very much

@jharding
Copy link
Contributor Author

Check out the remote section of the README.

Is JSONP supported?

You should be able to use JSONP by setting dataType to jsonp. I haven't actually tested this though so let me know if you experience any problems.

$('.typeahead').typeahead({
  name: 'jsonpExample',
  remote: {
    // ...
    dataType: 'jsonp'
  }
});

Can I make XHR request?

Not really sure what you mean by this.

@stayce
Copy link

stayce commented Apr 11, 2013

Thanks @jharding , jsonp seems to be working.

@zemirco
Copy link

zemirco commented Aug 7, 2013

jsonp doesn't work for me. See the example using the Bing Maps API for querying locations. I always get Uncaught SyntaxError: Unexpected token :

Test as much as you want. It's not a production key :)

@zh99998
Copy link

zh99998 commented Sep 18, 2013

seems there is no way to set jsonpCallback?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Allow remote to be a callback
8 participants