Skip to content

Instantly share code, notes, and snippets.

@TNowalk
Last active March 12, 2020 14:45
Show Gist options
  • Save TNowalk/587125f87b0aae1d1a9351c5a9bd965a to your computer and use it in GitHub Desktop.
Save TNowalk/587125f87b0aae1d1a9351c5a9bd965a to your computer and use it in GitHub Desktop.
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