Javascript:在请求对象„的情况下,使用模式Null对象模式、RORO、undefined等作为Get函数的返回参数;未找到“;
首先,我不确定这个话题是否属于StackOverflow。然而,我发现了一些关于其他编程语言的讨论,这些语言涉及StackOverflow主题,但不涉及Javascript。所以,我要把我的问题放到拳击场上: 处理Javascript中假设的GetUserByUsername函数中可能出现的“未找到”情况的最佳方式/模式是什么。 我为什么这么问?我想在整个项目中遵循一定的编码标准 我的更具体的场景如下所示:Javascript:在请求对象„的情况下,使用模式Null对象模式、RORO、undefined等作为Get函数的返回参数;未找到“;,javascript,oop,null-object-pattern,Javascript,Oop,Null Object Pattern,首先,我不确定这个话题是否属于StackOverflow。然而,我发现了一些关于其他编程语言的讨论,这些语言涉及StackOverflow主题,但不涉及Javascript。所以,我要把我的问题放到拳击场上: 处理Javascript中假设的GetUserByUsername函数中可能出现的“未找到”情况的最佳方式/模式是什么。 我为什么这么问?我想在整个项目中遵循一定的编码标准 我的更具体的场景如下所示: 我有一个类用户 我有一个用户列表,其中包含 类用户 我查找某个用户,但该用户不查找 存
- 我有一个类用户
- 我有一个用户列表,其中包含 类用户
- 我查找某个用户,但该用户不查找 存在于列表中
- 返回未定义
- RORO(接收对象,返回对象)
- 空对象模式
- 抛出自定义错误
module.exports = class User {
constructor() {
this.userName = null,
this.name = null,
this.age = null
}
...
getName() {
console.log(this.name);
}
}
在我的代码中,我有一个函数,它提供了从用户列表中按用户名返回某个用户的功能。该列表是一个数组,由类user的实例组成
module.exports = class User {
constructor() {
this.userName = null,
this.name = null,
this.age = null
}
...
getName() {
console.log(this.name);
}
}
一个简单的实现可能是这样的:
{
...
getUserByUsername(pUserName) {
/* listOfUsers array with objects of the class User */
var lUser = this.listOfUsers.find(user => user.userName === pUserName);
return lUser;
}
...
}
在某些情况下,传递的用户名可能不属于某个用户。因此找不到任何用户
我怎么办
1.)返回undefined-与示例代码一样
/* We expect "Unknown" is not a user name in that list*/
var lRequestedUser = getUserByUsername("Unknown");
/* Check if requested user is undefined. Note: I'm using lodash for staff like that */
if(_.undefined(lRequestedUser)) {
//Handling
}
lRequestedUser.getName();
2.)RORO(接收对象,返回对象)
我将一个对象传递给我的函数,并返回一个对象作为结果。在我返回的对象中,我有一个指示器,显示操作是否成功
getUserByUsername(pParams) {
if(_.undefined(pParams.userName)) {
//Throw custom error
}
var lReturnObject = {
isSuccessfull: false,
data: null
}
/* listOfUsers array with objects of the class User */
var lUser = this.listOfUsers.find(user => user.userName === pParams.userName);
if(!(_.undefined(lUser))) {
lReturnObject.isSuccessfull = true;
lReturnObject.data = lUser
}
return lUser;
}
...
}
/*
Building a object which is passed to the function. Username is a member of that object
*/
var lRequest = {
userName: "Unknown"
}
/* We expect "Unknown" is not a user name in that list*/
var lRequestedUser = getUserByUsername(lRequest);
if(!(lRequestedUser.isSuccessfull)) {
//Handling
}
lRequestedUser.data.getName();
3.)空对象模式
我不喜欢这个解决方案的一点是,如果主类得到一个附加函数,我总是必须增强空对象的类
module.exports = class NullUser {
constructor() {
this.userName = null,
this.name = null,
this.age = null
}
...
getName() {
console.log(this.name);
}
}
{
...
getUserByUsername(pUserName) {
/* listOfUsers array with objects of the class User */
var lUser = this.listOfUsers.find(user => user.userName === pUserName);
if(_.undefined(lUser)) {
return new NullUser();
}
return lUser;
}
...
}
/* We expect "Unknown" is not a user name in that list*/
var lRequestedUser = getUserByUsername("Unknown");
lRequestedUser.getName();
4.)抛出自定义错误
{
...
getUserByUsername(pUserName) {
/* listOfUsers array with objects of the class User */
var lUser = this.listOfUsers.find(user => user.userName === pUserName);
if(_.undefined(lUser)) {
throw new CustomError(...);
}
return lUser;
}
...
}
/* We expect "Unknown" is not a user name in that list*/
try {
var lRequestedUser = getUserByUsername("Unknown");
lRequestedUser.getName();
} catch (e) {
if (e instanceof CustomError) {
//Handling
}
}
就我个人而言,我更喜欢返回包含指示符的对象的选项,以及抛出自定义错误的选项。该示例是同步的。在我的项目中,我也有异步代码。我正在为此使用承诺
那么,有什么想法是“最好”的解决方案,或者我更喜欢的方式吗?答案是,在我看来,这取决于你的想法! 您提到的所有方法都有特定的用例,每个用例都占主导地位。让我们逐一进行讨论。(最后还有一位评论家) 带有回调的异步应用程序 尽管回调被视为陈旧而不流行,但它们给了我们所谓的“多重返回值”的灵活性
- 在这里,抛出错误将无法按预期工作。也就是说,您不能用try-catch捕捉抛出的错误。当然,您可以“返回”自定义错误。但这似乎毫无意义,因为您可以单独返回“状态”
- 使用附加的
参数返回空对象或RORO没有意义。不过,您可能更愿意放弃状态
,而选择空对象或RORO状态
带承诺的异步应用程序/async wait 在这里,抛出错误将起作用。如果您使用async Wait,则try-catch的捕获将获得错误。或者,如果您按原样使用承诺,则承诺链的捕获将获得错误 同步应用程序 抛出错误和使用try-catch的效果与预期一样。然而,在使用任何第三方服务的实际应用程序中,这将是一种罕见的情况 然而使用异常毕竟存在一个问题。是否将“无数据”场景视为错误取决于业务逻辑
固执己见的回答 在看到了良好的应用程序和高度不可维护的巨石之后,我会给出我个人的偏好。但请记住,这可能不是最终的解决方案 注:此(自以为是的)解决方案基于以下事实:
// Controller code
async signIn(name, email) {
try {
let user = await userDao.getUserByUserName(name);
if (!user.exists) {
user = await userDao.createUser(name, email);
}
return user;
} catch(e) {
// handle error
}
}
// Controller code
async signIn(name, email) {
try {
let result = await userDao.getUserByUserName(name);
if (!result.user) {
result = await userDao.createUser(name, email);
}
return result.user;
} catch(e) {
// handle error
}
}