Skip to content

Instantly share code, notes, and snippets.

@ajcrites
Last active August 29, 2015 14:19
Show Gist options
  • Save ajcrites/a9588bdfe76fc74c2764 to your computer and use it in GitHub Desktop.
Save ajcrites/a9588bdfe76fc74c2764 to your computer and use it in GitHub Desktop.
/**
* Exercise in consolidating common response handling using promises
* Duplicated code is on lines 34 and 68. How can we consolidate it?
*/
var http = require("http"),
express = require("express"),
errorFactory = require("error-factory"),
app = express(),
// Custom errors for common response problems. These errors are emitted
// by various requests when bad things happen
EmptyResponseError = errorFactory("EmptyResponseError", {status: 404}),
BadRequestError = errorFactory("BadRequestError", {status: 400}),
ServerError = errorFactory("ServerError", {status: 500});
app.use("/foo", function (req, res, next) {
new Promise(function (resolve, reject) {
if (req.query.hasOwnProperty("empty")) {
// You may throw an error -- this counts as a rejection
throw new EmptyResponseError;
}
else if (req.query.hasOwnProperty("client")) {
throw new BadRequestError;
}
else if (req.query.hasOwnProperty("server")) {
throw new ServerError;
}
resolve();
}).then(
function () {
res.status(200).end("foo");
},
next
);
});
app.use("/bar", function (req, res, next) {
new Promise(function (resolve, reject) {
if (req.query.hasOwnProperty("empty")) {
// Calling `reject` explicitly is also acceptable. This is done
// so that the implementation of the /bar route is different from
// the /foo route which would ordinarily be the case. This
// duplication is not at issue right now
reject(new EmptyResponseError);
}
else if (req.query.hasOwnProperty("client")) {
reject(new BadRequestError);
}
else if (req.query.hasOwnProperty("server")) {
reject(new ServerError);
}
resolve();
}).then(
function () {
res.status(200).end("bar");
},
next
);
});
app.use(function (err, req, res, next) {
res.status(err.status || 500).json(err);
});
if (require.main === module) {
http.createServer(app).listen(process.env.PORT || 3001, function () {
console.log("Listening on port", process.env.PORT || 3001);
});
}
module.exports = app;
{
"name": "promise-problem",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"bluebird": "^2.9.24",
"error-factory": "^0.1.5",
"express": "^4.12.3"
},
"devDependencies": {
"supertest": "^0.15.0"
}
}
var app = require("supertest")(require("./")),
assert = require("assert");
describe("Routes", function () {
describe("/foo", function () {
it("emit foo", function (done) {
app
.get("/foo")
.expect(200)
.expect(function (res) {
assert.equal("foo", res.text);
})
.end(done);
});
it("emit 404 for empty", function (done) {
app
.get("/foo?empty")
.expect(404)
.end(done);
});
it("emit 400 for client", function (done) {
app
.get("/foo?client")
.expect(400)
.end(done);
});
it("emit 500 for client", function (done) {
app
.get("/foo?server")
.expect(500)
.end(done);
});
});
describe("/bar", function () {
it("emit bar", function (done) {
app
.get("/bar")
.expect(200)
.expect(function (res) {
assert.equal("bar", res.text);
})
.end(done);
});
it("emit 404 for empty", function (done) {
app
.get("/bar?empty")
.expect(404)
.end(done);
});
it("emit 400 for client", function (done) {
app
.get("/bar?client")
.expect(400)
.end(done);
});
it("emit 500 for client", function (done) {
app
.get("/bar?server")
.expect(500)
.end(done);
});
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment