Skip to content

Commit

Permalink
Merge pull request #1027 from ajfranzoia/support-async-timeout
Browse files Browse the repository at this point in the history
Support function timeout via async.timeout wrapper
  • Loading branch information
aearly committed Mar 7, 2016
2 parents f755793 + 0d87dd0 commit 4f61814
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 0 deletions.
3 changes: 3 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -120,6 +121,7 @@ export default {
some: some,
someLimit: someLimit,
sortBy: sortBy,
timeout: timeout,
times: times,
timesLimit: timesLimit,
timesSeries: timesSeries,
Expand Down Expand Up @@ -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,
Expand Down
36 changes: 36 additions & 0 deletions lib/timeout.js
Original file line number Diff line number Diff line change
@@ -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;
}
48 changes: 48 additions & 0 deletions mocha_test/timeout.js
Original file line number Diff line number Diff line change
@@ -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();
});
});

});
46 changes: 46 additions & 0 deletions test/test-async.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
});
};

0 comments on commit 4f61814

Please sign in to comment.