Last active
August 7, 2017 23:05
-
-
Save IronSavior/d83815668b1ea0b5cc56569896c0c88c to your computer and use it in GitHub Desktop.
Composed error handling policy -- mix sync/async without missing errors
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
const error_policy = require('./error-policy'); | |
// EventEmitter example | |
const {Readable} = require('stream'); | |
class MyReadable extends Readable { | |
constructor(){ | |
super(...arguments); | |
this.policy = error_policy(e => this.emit('error', e)); | |
} | |
_read(){ | |
// No async calls, but error policy expressed more simply than with explicit try/catch structures | |
this.policy.enforce(_ => this.push(some_sync_call())); | |
} | |
} | |
// Transform stream with mix of sync/async | |
const {Transform} = require('stream'); | |
class MyTransform extends Transform { | |
_transform( chunk, enc, done ){ | |
let policy = error_policy(done); | |
policy.enforce(_ => { | |
sync_thing(); | |
async_thing(policy.fn(result => { | |
// By wrapping in policy.fn() we can be CERTAIN that errors thrown in async code are handled | |
other_sync_thing(); // Any throws here will pass error to done() | |
done(); // call to done with no arg signals success | |
})); | |
}); | |
} | |
} | |
// Promise example -- promises capture throws fairly well until you introduce an async call | |
function promise_example(){ | |
return Promise.new((resolve, reject) => { | |
async_thing(error_policy(reject).fn(result => | |
resolve(sync_thing(result)) | |
)); | |
}); | |
} | |
// Async calllback example | |
function async_callback_example(){ | |
let policy = error_policy(console.trace); | |
setImmediate(policy.fn(sync_thing)); | |
} | |
// Predicate example | |
function predicate_example(){ | |
// pretend "this" is an object managing an array of resources and has an error policy property. | |
// We want to call sync_operation on each resource regardless of errors, but we also want to handle those errors. | |
this.resources.forEach(this.policy.fn(item => item.sync_operation())); | |
} |
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
"use strict"; | |
// Composed error handling policy -- Sugar to make it easier to properly handle errors in mixed sync/async code | |
module.exports = function make_error_policy( error_handler ){ | |
let enforce = (f, ...args) => { | |
try{ | |
return f(...args); | |
} catch(e){ | |
error_handler(e); | |
} | |
}; | |
let fn = (f, ...bound_args) => (...args) => enforce(f, ...bound_args, ...args); | |
return {enforce, fn}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment