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