Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
15403 manish.sha 1
/*
2
 * typeahead.js
3
 * https://github.com/twitter/typeahead.js
4
 * Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT
5
 */
6
 
7
var Transport = (function() {
8
  'use strict';
9
 
10
  var pendingRequestsCount = 0,
11
      pendingRequests = {},
12
      maxPendingRequests = 6,
13
      sharedCache = new LruCache(10);
14
 
15
  // constructor
16
  // -----------
17
 
18
  function Transport(o) {
19
    o = o || {};
20
 
21
    this.cancelled = false;
22
    this.lastUrl = null;
23
 
24
    this._send = o.transport ? callbackToDeferred(o.transport) : $.ajax;
25
    this._get = o.rateLimiter ? o.rateLimiter(this._get) : this._get;
26
 
27
    // eh, should this even exist? relying on the browser's cache may be enough
28
    this._cache = o.cache === false ? new LruCache(0) : sharedCache;
29
  }
30
 
31
  // static methods
32
  // --------------
33
 
34
  Transport.setMaxPendingRequests = function setMaxPendingRequests(num) {
35
    maxPendingRequests = num;
36
  };
37
 
38
  Transport.resetCache = function resetCache() {
39
    sharedCache.reset();
40
  };
41
 
42
  // instance methods
43
  // ----------------
44
 
45
  _.mixin(Transport.prototype, {
46
 
47
    // ### private
48
 
49
    _get: function(url, o, cb) {
50
      var that = this, jqXhr;
51
 
52
      // #149: don't make a network request if there has been a cancellation
53
      // or if the url doesn't match the last url Transport#get was invoked with
54
      if (this.cancelled || url !== this.lastUrl) { return; }
55
 
56
      // a request is already in progress, piggyback off of it
57
      if (jqXhr = pendingRequests[url]) {
58
        jqXhr.done(done).fail(fail);
59
      }
60
 
61
      // under the pending request threshold, so fire off a request
62
      else if (pendingRequestsCount < maxPendingRequests) {
63
        pendingRequestsCount++;
64
        pendingRequests[url] =
65
          this._send(url, o).done(done).fail(fail).always(always);
66
      }
67
 
68
      // at the pending request threshold, so hang out in the on deck circle
69
      else {
70
        this.onDeckRequestArgs = [].slice.call(arguments, 0);
71
      }
72
 
73
      function done(resp) {
74
        cb && cb(null, resp);
75
        that._cache.set(url, resp);
76
      }
77
 
78
      function fail() {
79
        cb && cb(true);
80
      }
81
 
82
      function always() {
83
        pendingRequestsCount--;
84
        delete pendingRequests[url];
85
 
86
        // ensures request is always made for the last query
87
        if (that.onDeckRequestArgs) {
88
          that._get.apply(that, that.onDeckRequestArgs);
89
          that.onDeckRequestArgs = null;
90
        }
91
      }
92
    },
93
 
94
    // ### public
95
 
96
    get: function(url, o, cb) {
97
      var resp;
98
 
99
      if (_.isFunction(o)) {
100
        cb = o;
101
        o = {};
102
      }
103
 
104
      this.cancelled = false;
105
      this.lastUrl = url;
106
 
107
      // in-memory cache hit
108
      if (resp = this._cache.get(url)) {
109
        // defer to stay consistent with behavior of ajax call
110
        _.defer(function() { cb && cb(null, resp); });
111
      }
112
 
113
      else {
114
        this._get(url, o, cb);
115
      }
116
 
117
      // return bool indicating whether or not a cache hit occurred
118
      return !!resp;
119
    },
120
 
121
    cancel: function() {
122
      this.cancelled = true;
123
    }
124
  });
125
 
126
  return Transport;
127
 
128
  // helper functions
129
  // ----------------
130
 
131
  function callbackToDeferred(fn) {
132
    return function customSendWrapper(url, o) {
133
      var deferred = $.Deferred();
134
 
135
      fn(url, o, onSuccess, onError);
136
 
137
      return deferred;
138
 
139
      function onSuccess(resp) {
140
        // defer in case fn is synchronous, otherwise done
141
        // and always handlers will be attached after the resolution
142
        _.defer(function() { deferred.resolve(resp); });
143
      }
144
 
145
      function onError(err) {
146
        // defer in case fn is synchronous, otherwise done
147
        // and always handlers will be attached after the resolution
148
        _.defer(function() { deferred.reject(err); });
149
      }
150
    };
151
  }
152
})();