Last active
October 12, 2018 03:27
-
-
Save LiamKarlMitchell/7185433f5f62ce04e6218d76b2fdf3ec to your computer and use it in GitHub Desktop.
Javascript Async Patterns
This file contains hidden or 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
// Given an Async Function (Not a promise) this class will ensure that the run method can only run 1 instance of that async operation at a time. | |
class AsyncSingleInstance { | |
// Soon we will have private fields? https://github.com/tc39/proposal-class-fields#private-fields | |
//#inProgress; | |
//#asyncFunction; | |
constructor(asyncFunction) { | |
this.inProgress = false; | |
this.asyncFunction = asyncFunction; | |
} | |
get isRunning() { | |
return this.inProgress; | |
} | |
// Ensures only one instance of the asyncFunction will run at once, will return a promise that resolves to the result or errors if already in use. | |
async run() { | |
if (this.inProgress) { | |
throw new Error('Task '+this.asyncFunction.name+' is already in progress.'); | |
} | |
this.inProgress = true; | |
try { | |
var result = await this.asyncFunction(...arguments); | |
// Ensure we are not in progress anymore. | |
this.inProgress = false; | |
return result; | |
} catch(e) { | |
// Ensure we are not in progress anymore. | |
this.inProgress = false; | |
throw e; | |
} | |
} | |
} | |
module.exports = AsyncSingleInstance; |
This file contains hidden or 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
// Useful for mocking a long to run async process. | |
function delay(ms, result) { | |
return new Promise(function(resolve, reject) { | |
setTimeout(function() { | |
resolve(result); | |
}, ms); | |
}); | |
} | |
function delayError(ms, error) { | |
return new Promise(function(resolve, reject) { | |
setTimeout(function() { | |
reject(error); | |
}, ms); | |
}); | |
} | |
module.exports.delay = delay; | |
module.exports.delayError = delayError; |
This file contains hidden or 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
async function Disposable(delegate, action, argArray = [], disposer = "dispose") { | |
var disposable = await Promise.resolve(delegate()); | |
try { | |
var results = await action(disposable, ... argArray); | |
} finally { | |
if (typeof disposer === 'string' || disposer instanceof String) { | |
if (disposable[disposer] instanceof Function) { | |
await Promise.resolve(disposable[disposer]()); | |
} | |
} else if (disposer instanceof Function) { | |
await Promise.resolve(disposer(disposable)); | |
} | |
} | |
return results; | |
} | |
module.exports = Disposable; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Idea for having a friendlier to call syntax for Disposable for a specific purpose such as getting a mysql connection from a pool.
Would need to make a custom one that uses "release" as the disposer
Of course could always have one where there are two args for the object to call on for a delegate and the delegate action to call
UsingConnectionPool(pool, asyncAction)...