1 | define([ |
---|
2 | './util', |
---|
3 | '../errors/RequestTimeoutError', |
---|
4 | '../errors/CancelError', |
---|
5 | '../_base/array', |
---|
6 | '../has!host-browser?../_base/window:', |
---|
7 | '../has!host-browser?dom-addeventlistener?:../on:' |
---|
8 | ], function(util, RequestTimeoutError, CancelError, array, win, on){ |
---|
9 | // avoid setting a timer per request. It degrades performance on IE |
---|
10 | // something fierece if we don't use unified loops. |
---|
11 | var _inFlightIntvl = null, |
---|
12 | _inFlight = []; |
---|
13 | |
---|
14 | function watchInFlight(){ |
---|
15 | // summary: |
---|
16 | // internal method that checks each inflight XMLHttpRequest to see |
---|
17 | // if it has completed or if the timeout situation applies. |
---|
18 | |
---|
19 | var now = +(new Date); |
---|
20 | |
---|
21 | // we need manual loop because we often modify _inFlight (and therefore 'i') while iterating |
---|
22 | for(var i = 0, dfd; i < _inFlight.length && (dfd = _inFlight[i]); i++){ |
---|
23 | var response = dfd.response, |
---|
24 | options = response.options; |
---|
25 | if((dfd.isCanceled && dfd.isCanceled()) || (dfd.isValid && !dfd.isValid(response))){ |
---|
26 | _inFlight.splice(i--, 1); |
---|
27 | watch._onAction && watch._onAction(); |
---|
28 | }else if(dfd.isReady && dfd.isReady(response)){ |
---|
29 | _inFlight.splice(i--, 1); |
---|
30 | dfd.handleResponse(response); |
---|
31 | watch._onAction && watch._onAction(); |
---|
32 | }else if(dfd.startTime){ |
---|
33 | // did we timeout? |
---|
34 | if(dfd.startTime + (options.timeout || 0) < now){ |
---|
35 | _inFlight.splice(i--, 1); |
---|
36 | // Cancel the request so the io module can do appropriate cleanup. |
---|
37 | dfd.cancel(new RequestTimeoutError('Timeout exceeded', response)); |
---|
38 | watch._onAction && watch._onAction(); |
---|
39 | } |
---|
40 | } |
---|
41 | } |
---|
42 | |
---|
43 | watch._onInFlight && watch._onInFlight(dfd); |
---|
44 | |
---|
45 | if(!_inFlight.length){ |
---|
46 | clearInterval(_inFlightIntvl); |
---|
47 | _inFlightIntvl = null; |
---|
48 | } |
---|
49 | } |
---|
50 | |
---|
51 | function watch(dfd){ |
---|
52 | // summary: |
---|
53 | // Watches the io request represented by dfd to see if it completes. |
---|
54 | // dfd: Deferred |
---|
55 | // The Deferred object to watch. |
---|
56 | // response: Object |
---|
57 | // The object used as the value of the request promise. |
---|
58 | // validCheck: Function |
---|
59 | // Function used to check if the IO request is still valid. Gets the dfd |
---|
60 | // object as its only argument. |
---|
61 | // ioCheck: Function |
---|
62 | // Function used to check if basic IO call worked. Gets the dfd |
---|
63 | // object as its only argument. |
---|
64 | // resHandle: Function |
---|
65 | // Function used to process response. Gets the dfd |
---|
66 | // object as its only argument. |
---|
67 | if(dfd.response.options.timeout){ |
---|
68 | dfd.startTime = +(new Date); |
---|
69 | } |
---|
70 | |
---|
71 | if(dfd.isFulfilled()){ |
---|
72 | // bail out if the deferred is already fulfilled |
---|
73 | return; |
---|
74 | } |
---|
75 | |
---|
76 | _inFlight.push(dfd); |
---|
77 | if(!_inFlightIntvl){ |
---|
78 | _inFlightIntvl = setInterval(watchInFlight, 50); |
---|
79 | } |
---|
80 | |
---|
81 | // handle sync requests separately from async: |
---|
82 | // http://bugs.dojotoolkit.org/ticket/8467 |
---|
83 | if(dfd.response.options.sync){ |
---|
84 | watchInFlight(); |
---|
85 | } |
---|
86 | } |
---|
87 | |
---|
88 | watch.cancelAll = function cancelAll(){ |
---|
89 | // summary: |
---|
90 | // Cancels all pending IO requests, regardless of IO type |
---|
91 | try{ |
---|
92 | array.forEach(_inFlight, function(dfd){ |
---|
93 | try{ |
---|
94 | dfd.cancel(new CancelError('All requests canceled.')); |
---|
95 | }catch(e){} |
---|
96 | }); |
---|
97 | }catch(e){} |
---|
98 | }; |
---|
99 | |
---|
100 | if(win && on && win.doc.attachEvent){ |
---|
101 | // Automatically call cancel all io calls on unload in IE |
---|
102 | // http://bugs.dojotoolkit.org/ticket/2357 |
---|
103 | on(win.global, 'unload', function(){ |
---|
104 | watch.cancelAll(); |
---|
105 | }); |
---|
106 | } |
---|
107 | |
---|
108 | return watch; |
---|
109 | }); |
---|