From 4f6ece185428b16c248ecb994b6d8f5849e46c83 Mon Sep 17 00:00:00 2001 From: Hubert Argasinski Date: Sat, 20 May 2017 23:17:08 -0400 Subject: [PATCH] allow fn wrapped in timeout to be called multiple times (fixes #1418) --- lib/timeout.js | 41 ++++++++++++++++++++--------------------- mocha_test/timeout.js | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 21 deletions(-) diff --git a/lib/timeout.js b/lib/timeout.js index 475b20889..ebd81b1a3 100644 --- a/lib/timeout.js +++ b/lib/timeout.js @@ -43,33 +43,32 @@ import wrapAsync from './internal/wrapAsync'; * }); */ export default function timeout(asyncFn, milliseconds, info) { - var originalCallback, timer; - var timedOut = false; + var fn = wrapAsync(asyncFn); - function injectedCallback() { - if (!timedOut) { - originalCallback.apply(null, arguments); - clearTimeout(timer); - } - } + return initialParams(function (args, callback) { + var timedOut = false; + var timer; - function timeoutCallback() { - var name = asyncFn.name || 'anonymous'; - var error = new Error('Callback function "' + name + '" timed out.'); - error.code = 'ETIMEDOUT'; - if (info) { - error.info = info; + function timeoutCallback() { + var name = asyncFn.name || 'anonymous'; + var error = new Error('Callback function "' + name + '" timed out.'); + error.code = 'ETIMEDOUT'; + if (info) { + error.info = info; + } + timedOut = true; + callback(error); } - timedOut = true; - originalCallback(error); - } - var fn = wrapAsync(asyncFn); + args.push(function () { + if (!timedOut) { + callback.apply(null, arguments); + clearTimeout(timer); + } + }); - return initialParams(function (args, origCallback) { - originalCallback = origCallback; // setup timer and call original function timer = setTimeout(timeoutCallback, milliseconds); - fn.apply(null, args.concat(injectedCallback)); + fn.apply(null, args); }); } diff --git a/mocha_test/timeout.js b/mocha_test/timeout.js index be4128372..cd4a75115 100644 --- a/mocha_test/timeout.js +++ b/mocha_test/timeout.js @@ -69,4 +69,40 @@ describe('timeout', function () { done(); }); }); + + it('timeout with multiple calls (#1418)', function(done) { + var timeout = async.timeout(function asyncFn(n, callback) { + if (n < 1) { + setTimeout(function() { + callback(null, 'I will time out'); + }, 75); + } else { + async.setImmediate(function() { + callback(null, 'I didn\'t time out'); + }) + } + }, 50); + + async.series([ + function(cb) { + timeout(0, function(err, result) { + expect(err.message).to.equal('Callback function "asyncFn" timed out.'); + expect(err.code).to.equal('ETIMEDOUT'); + expect(err.info).to.equal(undefined); + expect(result).to.equal(undefined); + cb(); + }); + }, + function(cb) { + timeout(1, function(err, result) { + expect(err).to.equal(null); + expect(result).to.equal('I didn\'t time out'); + cb(); + }); + } + ], function(err) { + expect(err).to.equal(null); + done(); + }); + }) });