summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Early <alexander.early@gmail.com>2016-03-06 20:40:33 -0800
committerAlex Early <alexander.early@gmail.com>2016-03-06 20:40:33 -0800
commit4f6181459a43bbffab9493f08e26383d9b68ef52 (patch)
tree87e1fb4e325831d55d7ce3490201ec3ef9720a24
parentf75579366c69940dad5d4ee0b6b7070485701481 (diff)
parent0d87dd08374f95df0ba1449cdbb4bc5db320dee7 (diff)
downloadasync-4f6181459a43bbffab9493f08e26383d9b68ef52.tar.gz
Merge pull request #1027 from ajfranzoia/support-async-timeout
Support function timeout via async.timeout wrapper
-rw-r--r--lib/index.js3
-rw-r--r--lib/timeout.js36
-rw-r--r--mocha_test/timeout.js48
-rwxr-xr-xtest/test-async.js46
4 files changed, 133 insertions, 0 deletions
diff --git a/lib/index.js b/lib/index.js
index 2e27f25..300491d 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -55,6 +55,7 @@ import setImmediate from './setImmediate';
import some from './some';
import someLimit from './someLimit';
import sortBy from './sortBy';
+import timeout from './timeout';
import times from './times';
import timesLimit from './timesLimit';
import timesSeries from './timesSeries';
@@ -120,6 +121,7 @@ export default {
some: some,
someLimit: someLimit,
sortBy: sortBy,
+ timeout: timeout,
times: times,
timesLimit: timesLimit,
timesSeries: timesSeries,
@@ -203,6 +205,7 @@ export {
some as some,
someLimit as someLimit,
sortBy as sortBy,
+ timeout as timeout,
times as times,
timesLimit as timesLimit,
timesSeries as timesSeries,
diff --git a/lib/timeout.js b/lib/timeout.js
new file mode 100644
index 0000000..c8c9dfd
--- /dev/null
+++ b/lib/timeout.js
@@ -0,0 +1,36 @@
+'use strict';
+
+export default function timeout(asyncFn, miliseconds) {
+ var originalCallback, timer;
+ var timedOut = false;
+
+ function injectedCallback() {
+ if (!timedOut) {
+ originalCallback.apply(null, arguments);
+ clearTimeout(timer);
+ }
+ }
+
+ function timeoutCallback() {
+ var error = new Error('Callback function timed out.');
+ error.code = 'ETIMEDOUT';
+ timedOut = true;
+ originalCallback(error);
+ }
+
+ function injectCallback(asyncFnArgs) {
+ // replace callback in asyncFn args
+ var args = Array.prototype.slice.call(asyncFnArgs, 0);
+ originalCallback = args[args.length - 1];
+ args[args.length - 1] = injectedCallback;
+ return args;
+ }
+
+ function wrappedFn() {
+ // setup timer and call original function
+ timer = setTimeout(timeoutCallback, miliseconds);
+ asyncFn.apply(null, injectCallback(arguments));
+ }
+
+ return wrappedFn;
+}
diff --git a/mocha_test/timeout.js b/mocha_test/timeout.js
new file mode 100644
index 0000000..8355eb6
--- /dev/null
+++ b/mocha_test/timeout.js
@@ -0,0 +1,48 @@
+var async = require('../lib');
+var expect = require('chai').expect;
+
+describe('timeout', function () {
+
+ it('timeout with series', function(done){
+ async.series([
+ async.timeout(function asyncFn(callback) {
+ setTimeout(function() {
+ callback(null, 'I didn\'t time out');
+ }, 50);
+ }, 200),
+ async.timeout(function asyncFn(callback) {
+ setTimeout(function() {
+ callback(null, 'I will time out');
+ }, 300);
+ }, 150)
+ ],
+ function(err, results) {
+ expect(err.message).to.equal('Callback function timed out.');
+ expect(err.code).to.equal('ETIMEDOUT');
+ expect(results[0]).to.equal('I didn\'t time out');
+ done();
+ });
+ });
+
+ it('timeout with parallel', function(done){
+ async.parallel([
+ async.timeout(function asyncFn(callback) {
+ setTimeout(function() {
+ callback(null, 'I didn\'t time out');
+ }, 50);
+ }, 200),
+ async.timeout(function asyncFn(callback) {
+ setTimeout(function() {
+ callback(null, 'I will time out');
+ }, 300);
+ }, 150)
+ ],
+ function(err, results) {
+ expect(err.message).to.equal('Callback function timed out.');
+ expect(err.code).to.equal('ETIMEDOUT');
+ expect(results[0]).to.equal('I didn\'t time out');
+ done();
+ });
+ });
+
+});
diff --git a/test/test-async.js b/test/test-async.js
index bd103bf..b4aef6c 100755
--- a/test/test-async.js
+++ b/test/test-async.js
@@ -3825,3 +3825,49 @@ exports['asyncify'] = {
return promises;
}, {})
};
+
+exports['timeout'] = function (test) {
+ test.expect(3);
+
+ async.series([
+ async.timeout(function asyncFn(callback) {
+ setTimeout(function() {
+ callback(null, 'I didn\'t time out');
+ }, 50);
+ }, 200),
+ async.timeout(function asyncFn(callback) {
+ setTimeout(function() {
+ callback(null, 'I will time out');
+ }, 300);
+ }, 150)
+ ],
+ function(err, results) {
+ test.ok(err.message === 'Callback function timed out.');
+ test.ok(err.code === 'ETIMEDOUT');
+ test.ok(results[0] === 'I didn\'t time out');
+ test.done();
+ });
+};
+
+exports['timeout with parallel'] = function (test) {
+ test.expect(3);
+
+ async.parallel([
+ async.timeout(function asyncFn(callback) {
+ setTimeout(function() {
+ callback(null, 'I didn\'t time out');
+ }, 50);
+ }, 200),
+ async.timeout(function asyncFn(callback) {
+ setTimeout(function() {
+ callback(null, 'I will time out');
+ }, 300);
+ }, 150)
+ ],
+ function(err, results) {
+ test.ok(err.message === 'Callback function timed out.');
+ test.ok(err.code === 'ETIMEDOUT');
+ test.ok(results[0] === 'I didn\'t time out');
+ test.done();
+ });
+};