我有一個Node 8/Express 4/Mongoose 4 API,並希望推廣一些代碼,以便我可以將其重用於其他部分。承諾鏈與簡單性
考慮下面的代碼,將創建一個新用戶:
function postUser(req, res, next) {
var body = req.body;
if ("data" in body) {
var user = new User(body.data);
user.save(function(err, savedUser) {
if (err) {
if (err.name === 'MongoError' && err.code === 11000) {
// user already exists
res.status(400).json({status: "fail", message: "User already exists"});
} else {
return next(err);
}
} else {
// user successfully saved
res.json({status: "success", data: savedUser});
}
});
} else {
// malformed body
res.status(400).json({status: "fail", message: "Malformed body"});
}
}
讓我們假設我有其他的功能,會做類似的工作,他們中的一些回調地獄。我如何最好地概括上述代碼?我想過用諾言鏈是這樣的:
function postUser(req, res, next) {
validateBody(req.body)
.then(createNewUser)
.then(user => sendUser(user, res))
.catch(e => handleErrors(e, res));
}
function validateBody(body) {
return new Promise(function(resolve, reject) {
if ("data" in body) {
resolve(body.data);
} else {
reject(new InvalidBodyError());
}
});
}
function createNewUser(userObj) {
return new Promise(function(resolve, reject) {
var user = new User(userObj);
user.save(function(err, savedUser) {
if (err) {
if (err.name === 'MongoError' && err.code === 11000) {
// user already exists
reject(new UserAlreadyExistsError(userObj));
} else {
// other error
reject(err);
}
} else {
// user successfully saved
resolve(savedUser);
}
});
});
}
function handleErrors(e, res) {
if (e instanceof InvalidObjectIdError) handleInvalidObjectIdError(e, res)
else if (e instanceof UserNotFoundError) handleUserNotFoundError(e, res)
else if (e instanceof InvalidBodyError) handleInvalidBodyError(e, res)
else if (e instanceof UserAlreadyExistsError) handleUserAlreadyExistsError(e, res)
// TODO: handle unknown errors
}
正如你所看到的,它看起來更清潔,更可重複使用。但如何在負載下運行?我特別關心爲每個請求創建多個承諾。這是否規模?
解決這將是創建一個能夠解決通用的東西,然後擴展這個類實現特定的方法(僞)的通用基礎類的另一種方式:
class Action {
constructor() {}
postDoc(Base, req, res, next) {
var body = req.body;
if ("data" in body) {
var doc= new Base(body.data);
doc.save(function(err, savedDoc) {
if (err) {
if (err.name === 'MongoError' && err.code === 11000) {
// docalready exists
res.status(400).json({status: "fail", message: "Doc already exists"});
} else {
return next(err);
}
} else {
// user successfully saved
res.json({status: "success", data: savedDoc});
}
});
} else {
// malformed body
res.status(400).json({status: "fail", message: "Malformed body"});
}
}
}
class UserAction extends Action {
constructor() {
super();
}
postUser(body, req, res, next) {
this.postDoc(User, req, res, next);
}
}
class AnotherAction extends Action {
constructor() {
super();
}
postAnother(body, req, res, next) {
this.postDoc(AnotherBase, req, res, next);
}
}
,然後只用UserAction或AnotherAction(用戶是我的情況下的貓鼬模型)。 你更喜歡哪一個?
太棒了,謝謝! – 1FpGLLjZSZMx6k