Last active
March 12, 2020 14:45
-
-
Save TNowalk/587125f87b0aae1d1a9351c5a9bd965a to your computer and use it in GitHub Desktop.
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
const express = require('express') | |
const app = express() | |
const port = 3500 | |
app.get('/promise/resolved', (req, res) => { | |
testPromiseResolved().then(response => res.json(response)).catch(e => next(e)) | |
}) | |
app.get('/promise/rejected', (req, res, next) => { | |
testPromiseRejected().then(response => res.json(response)).catch(e => next(e)) | |
}) | |
app.get('/promise/errored', (req, res, next) => { | |
testPromiseErrored().then(response => res.json(response)).catch(e => next(e)) | |
}) | |
app.get('/promise/notrycatch', (req, res, next) => { | |
testPromiseNoTryCatch().then(response => res.json(response)).catch(e => next(e)) | |
}) | |
app.get('/chain/promise/rejected', (req, res, next) => { | |
testChainedPromiseRejected().then(response => res.json(response)).catch(e => next(e)) | |
}) | |
app.get('/await/resolved', async (req, res, next) => { | |
try { | |
res.json(await testPromiseResolved()) | |
} catch (e) { next(e) } | |
}) | |
app.get('/await/rejected', async (req, res, next) => { | |
try { | |
res.json(await testPromiseRejected()) | |
} catch (e) { next(e) } | |
}) | |
app.get('/await/errored', async (req, res, next) => { | |
try { | |
res.json(await testPromiseErrored()) | |
} catch (e) { next(e) } | |
}) | |
app.get('/await/notrycatch', async (req, res, next) => { | |
try { | |
res.json(await testPromiseNoTryCatch()) | |
} catch (e) { next(e) } | |
}) | |
app.get('/chain/await/rejected', async (req, res, next) => { | |
try { | |
res.json(await testChainedPromiseRejected()) | |
} catch (e) { next(e) } | |
}) | |
app.use((err, req, res, next) => { | |
if (res.headersSent) { | |
return next(err) | |
} | |
console.error('Caught error in middleware', err) | |
res.status(500).send({ | |
status: false, | |
error: true, | |
message: err.message, | |
stack: err.stack ? err.stack.split('\n') : null | |
}) | |
}) | |
function testPromiseResolved() { | |
return new Promise((resolve, reject) => { | |
setTimeout(() => { | |
resolve({ | |
test: 'testPromiseResolved', | |
status: true, | |
error: false | |
}) | |
}, 200) | |
}) | |
} | |
function testPromiseRejected() { | |
return new Promise((resolve, reject) => { | |
setTimeout(() => { | |
reject({ | |
test: 'testPromiseRejected', | |
status: false, | |
error: true, | |
message: 'testPromiseRejected: rejected' | |
}) | |
}, 200) | |
}) | |
} | |
function testPromiseErrored() { | |
return new Promise((resolve, reject) => { | |
setTimeout(() => { | |
try { | |
throw new Error('testPromiseErrored: error') | |
} catch (e) { | |
reject(e) | |
} | |
}, 200) | |
}) | |
} | |
function testPromiseNoTryCatch() { | |
return new Promise((resolve, reject) => { | |
// Doesn't work because the function has implicitly returned before the | |
// execution of the setTimeout as executed the lambda, so the implict catch | |
// for the promise isn't realized. | |
setTimeout(() => { | |
throw new Error('testPromiseNoTryCatch: error') | |
}, 200) | |
}) | |
} | |
function testChainedPromiseRejected() { | |
let p1 = new Promise((resolve, reject) => { | |
setTimeout(() => { | |
reject({ | |
test: 'testPromiseRejected', | |
status: false, | |
error: true, | |
message: 'testPromiseRejected: rejected' | |
}) | |
}, 200) | |
}) | |
let p2 = new Promise((resolve, reject) => { | |
p1.catch(e => { | |
e.message += ', added to the error' | |
reject(e) | |
}) | |
}) | |
return p2.catch(e => { | |
e.message += ', added more to the error' | |
throw e | |
}) | |
} | |
app.listen(port, () => console.log(`Error handling example app listening on port ${port}!`)) | |
process.on('uncaughtException', error => { | |
// This is an unexpected condition, the API should really exit and let | |
// whatever process/service handle the down state and restart in a known | |
// clean state. The error should be logged so that it can be investigated | |
// and handling can be added. | |
console.error('Caught unhandled exception, stopping the process!', error) | |
process.exit(1) | |
}) | |
process.on('unhandledRejection', error => { | |
// This is also an unexpected condition. All promises should have catches, either | |
// using .catch on a promise or using a try/catch when using await syntax. Eventually | |
// this condition will be an error that exits the process. We can catch here and log, | |
// but should decide if we want to throw as an error to exit the process (and auto restart) | |
// or simply log the error and move on. Knowing that an uncaught promise is an error condition | |
// that we did not expect, it has the same implications of an uncaught exception and the API | |
// could be in an unknown state - thusly it should throw an error and halt the process. | |
console.warn('Caught an unhandled promise rejection', error) | |
throw new Error('Unhandled Promise Rejection', error) | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment