Created
August 29, 2012 09:14
-
-
Save kyo-ago/3508901 to your computer and use it in GitHub Desktop.
JavaScript request controler(start, stop, restart)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
request.responseError = request.offlineError = request.timeoutError = function () { | |
request.callQueue('stop'); | |
alert('Network error\nDo you want to reconnect?'); | |
$('<button id="ok">ok</button><button id="cancel">cancel</button>').appendTo('body') | |
.find('#ok').click(function () { | |
request.callQueue('restart'); | |
}).end() | |
.find('#cancel').click(function () { | |
request.callQueue('abort'); | |
}).end() | |
; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function () { | |
var old_ajax = $.ajax; | |
$.ajax = function (options) { | |
var self = this; | |
var xhr; | |
var aborted = function () { | |
xhr && xhr.abort(); | |
}; | |
request.add(function (callback) { | |
options.success = callback.success; | |
options.error = callback.error; | |
xhr = old_ajax.call(self, options); | |
}, success, aborted, function () { | |
self.ajax(options); | |
}); | |
return aborted; | |
}; | |
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var request = { | |
// global response error | |
'responseError' : function (xhr_status) { | |
}, | |
// global offline error | |
'offlineError' : function () { | |
}, | |
// global timeout error | |
'timeoutError' : function () { | |
}, | |
// make id counter | |
'counter' : 0, | |
// current request queue | |
'queue' : {}, | |
// call queue function | |
'callQueue' : function (name) { | |
var keys = Object.keys(this.queue); | |
for (var i = 0, l = keys.length; i < l; ++i) { | |
var key = keys[i]; | |
var obj = this.queue[key]; | |
obj && obj[name] && obj[name](); | |
} | |
}, | |
// clear all queue | |
'clearQueue' : function () { | |
this.counter = 0; | |
this.queue = {}; | |
}, | |
// stop all request | |
'stopQueue' : function () { | |
var keys = Object.keys(this.queue); | |
for (var i = 0, l = keys.length; i < l; ++i) { | |
var key = keys[i]; | |
var obj = this.queue[key]; | |
if (!obj) { | |
continue; | |
} | |
obj['connectTimeout'] && clearTimeout(obj['connectTimeout']); | |
obj['sendTimeout'] && clearTimeout(obj['sendTimeout']); | |
delete obj['connectTimeout']; | |
delete obj['sendTimeout']; | |
} | |
}, | |
// request timeout | |
'timeout' : 15 * 1000, | |
// for UnitTest | |
'navigator' : navigator, | |
'add' : function (send, success, abort, restart) { | |
var self = this; | |
var queue_id = this.counter++; | |
var state = { | |
'restart' : function () { | |
delete self.queue[queue_id]; | |
restart(); | |
}, | |
'stop' : abort, | |
'abort' : function () { | |
delete self.queue[queue_id]; | |
abort(); | |
}, | |
'connectTimeout' : '', | |
'sendTimeout' : '' | |
}; | |
// this.queue is object(not array) | |
this.queue[queue_id + ''] = state; | |
state['connectTimeout'] = setTimeout(function () { | |
delete state['connectTimeout']; | |
self.stopQueue(); | |
abort(); | |
self.timeoutError(); | |
}, this.timeout); | |
state['sendTimeout'] = setTimeout(function () { | |
if (!self.navigator.onLine) { // for UnitTest | |
self.stopQueue(); | |
self.offlineError(); | |
self.navigator.onLine = true; | |
return; | |
} | |
send({ | |
'error' : function (xhr) { | |
self.stopQueue(); | |
self.responseError(xhr.status); | |
}, | |
'success' : function (json, xhr) { | |
clearTimeout(state['connectTimeout']); | |
delete self.queue[queue_id]; | |
success(json, xhr); | |
} | |
}); | |
}); | |
} | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
TestCase('request', { | |
'setUp' : function () { | |
this.clock = sinon.useFakeTimers(); | |
}, | |
'_init_request' : function () { | |
var req = {}; | |
req.request = function (success, error) { | |
var timeout = setTimeout(function () { | |
if (!req.request.error) { | |
success(); | |
} else { | |
error({ | |
'status' : 200 | |
}); | |
} | |
}); | |
return function () { | |
clearTimeout(timeout); | |
}; | |
}; | |
req.request.error = false; | |
request.responseError = this.stub(); | |
request.offlineError = this.stub(); | |
request.timeoutError = this.stub(); | |
request.clearQueue(); | |
return req; | |
}, | |
'_make_connection' : function (req) { | |
var self = this; | |
var conn = {}; | |
var abort; | |
conn.aborted = this.spy(function () { | |
abort && abort(); | |
}); | |
conn.send = this.spy(function (callback) { | |
abort = self.spy(req.request(self.spy(callback.success), self.spy(callback.error))); | |
}); | |
conn.success = this.stub(); | |
conn.restart = this.stub(); | |
return conn; | |
}, | |
'test10_request_success' : function () { | |
var self = this; | |
var req = self._init_request(); | |
var conn = self._make_connection(req); | |
request.add(conn.send, conn.success, conn.aborted, conn.restart); | |
this.clock.tick(100); | |
assertCalledOnce(conn.send); | |
assertCalledOnce(conn.success); | |
}, | |
'test10_request_error' : function () { | |
var self = this; | |
var req = self._init_request(); | |
var conn = self._make_connection(req); | |
req.request.error = true; | |
request.add(conn.send, conn.success, conn.aborted, conn.restart); | |
this.clock.tick(100); | |
assertCalledOnce(request.responseError); | |
}, | |
'test10_request_error_abort' : function () { | |
var self = this; | |
var req = self._init_request(); | |
var conn_a = self._make_connection(req); | |
var conn_b = self._make_connection(req); | |
request.responseError = this.spy(function () { | |
request.callQueue('abort'); | |
}); | |
req.request.error = true; | |
request.add(conn_a.send, conn_a.success, conn_a.aborted, conn_a.restart); | |
request.add(conn_b.send, conn_b.success, conn_b.aborted, conn_b.restart); | |
this.clock.tick(100); | |
assertNotCalled(conn_a.success); | |
assertNotCalled(conn_b.success); | |
assertCalledOnce(conn_a.aborted); | |
assertCalledOnce(conn_b.aborted); | |
assertCalledOnce(request.responseError); | |
assertEquals(request.queue, {}); | |
}, | |
'test10_request_error_redo' : function () { | |
var self = this; | |
var req = self._init_request(); | |
var conn_a = self._make_connection(req); | |
var conn_b = self._make_connection(req); | |
request.responseError = this.spy(function () { | |
request.callQueue('restart'); | |
}); | |
req.request.error = true; | |
request.add(conn_a.send, conn_a.success, conn_a.aborted, conn_a.restart); | |
request.add(conn_b.send, conn_b.success, conn_b.aborted, conn_b.restart); | |
this.clock.tick(100); | |
assertNotCalled(conn_a.success); | |
assertNotCalled(conn_b.success); | |
assertCalledOnce(conn_a.restart); | |
assertCalledOnce(conn_b.restart); | |
assertCalledOnce(request.responseError); | |
assertEquals(request.queue, {}); | |
}, | |
'test10_request_error_restop' : function () { | |
var self = this; | |
var req = self._init_request(); | |
var conn_a = self._make_connection(req); | |
var conn_b = self._make_connection(req); | |
request.responseError = this.spy(function () { | |
request.callQueue('stop'); | |
setTimeout(function () { | |
request.callQueue('restart'); | |
}); | |
}); | |
req.request.error = true; | |
request.add(conn_a.send, conn_a.success, conn_a.aborted, conn_a.restart); | |
request.add(conn_b.send, conn_b.success, conn_b.aborted, conn_b.restart); | |
this.clock.tick(100); | |
assertNotCalled(conn_a.success); | |
assertNotCalled(conn_b.success); | |
assertCalledOnce(conn_a.restart); | |
assertCalledOnce(conn_b.restart); | |
assertCalledOnce(request.responseError); | |
assertEquals(request.queue, {}); | |
}, | |
'test10_request_error_offline' : function () { | |
var self = this; | |
var req = self._init_request(); | |
var conn_a = self._make_connection(req); | |
var conn_b = self._make_connection(req); | |
request.navigator = { | |
'onLine' : false | |
}; | |
request.offlineError = this.spy(function () { | |
request.callQueue('abort'); | |
}); | |
request.add(conn_a.send, conn_a.success, conn_a.aborted, conn_a.restart); | |
request.add(conn_b.send, conn_b.success, conn_b.aborted, conn_b.restart); | |
this.clock.tick(100); | |
assertNotCalled(conn_a.success); | |
assertNotCalled(conn_b.success); | |
assertCalledOnce(conn_a.aborted); | |
assertCalledOnce(conn_b.aborted); | |
assertCalledOnce(request.offlineError); | |
assertEquals(request.queue, {}); | |
request.navigator = navigator; | |
}, | |
'test10_request_error_timeout' : function () { | |
var self = this; | |
var req = self._init_request(); | |
req.request = function () { | |
return function () {}; | |
}; | |
var conn = self._make_connection(req); | |
request.timeoutError = this.spy(function () { | |
request.callQueue('abort'); | |
}); | |
request.timeout = 100; | |
request.add(conn.send, conn.success, conn.aborted, conn.restart); | |
this.clock.tick(200); | |
assertNotCalled(conn.success); | |
assertCalledOnce(request.timeoutError); | |
assertEquals(request.queue, {}); | |
}, | |
'test10_request_error_timeout_redo' : function () { | |
var self = this; | |
var req = self._init_request(); | |
req.request = function () { | |
return function () {}; | |
}; | |
var conn = self._make_connection(req); | |
request.timeoutError = this.spy(function () { | |
request.callQueue('stop'); | |
setTimeout(function () { | |
request.callQueue('restart'); | |
}); | |
}); | |
request.timeout = 100; | |
request.add(conn.send, conn.success, conn.aborted, conn.restart); | |
this.clock.tick(200); | |
assertCalledOnce(conn.restart); | |
assertCalledOnce(request.timeoutError); | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment