Ramda IfElse 传递另一个参数的最佳方式
Ramda IfElse best way to pass another parameter
在我使用 express 和 mongoose 的 NodeJS 项目中,我决定使用 RamdaJS 来获得一些函数式编程的经验。
我有两个像
这样的预存挂钩
UserSchema.pre('save', async function (next) {
if (!this.isModified('username')) {
return next();
}
const total = await this.constructor.countUsersWithUsername(this.username);
if (total > 0) {
return next(new Error(`Username ${this.username} is already taken`));
}
return next();
});
UserSchema.pre('save', async function (next) {
if (!this.isModified('email')) {
return next();
}
const total = await this.constructor.countDocuments({ email: this.email });
if (total > 0) {
return next(new Error(`Email ${this.email} is taken`));
}
return next();
});
If 条件似乎是使用 Ramda 的好地方,我更改了我的代码
const total = await this.constructor.countUsersWithUsername(this.username);
const isUsernameTaken = R.ifElse(
R.gt(0),
() => next(),
() => next(new Error(`Username ${this.username} is already taken`))
);
return isUsernameTaken(total);
这行得通,但我开始考虑我可以将 IfElse 重构到一个不同的模块中,然后我需要传入 next 和一个标签,这样我就可以说 ${label} ${value} 已经被采用。
我将如何重构它?
Mongoose 也是基于 class 的,是否有功能库可以与 MongoDB 连接?
我不会费心用 Ramda 做这个。 Ramda 的 ifElse
偶尔很有用,但大多数时候并不值得。通常只需要一个条件表达式(三元)。请注意,我是 Ramda 的创始人和忠实粉丝;但我有很多时候现代 JS 也一样好,或者在这里,甚至更老的 JS。
这将是我的方法,而不是试图弄清楚如何在你的钩子中调用它:
const isTaken = (label) => (value, count, next) =>
count > 0
? next (new Error (`${label} ${value} is already taken`))
: next ()
const isUsernameTaken = isTaken('Username')
const isEmailTaken = isTaken('Email')
const next = (err) => {
console.log(err ? `${err}` : `Success`)
}
isUsernameTaken('Fred', 2, next);
isUsernameTaken('Wilma', 0, next);
isEmailTaken('fred@bedrock.com', 0, next)
isEmailTaken('wilma@stoneage.com', 1, next)
无论您是想要特定的助手 isUsernameTaken
和 isEmailTaken
还是只想调用通用的 isTaken
都将决定您是否应该柯里化第一个参数。应该很容易改变。
在我使用 express 和 mongoose 的 NodeJS 项目中,我决定使用 RamdaJS 来获得一些函数式编程的经验。
我有两个像
这样的预存挂钩UserSchema.pre('save', async function (next) {
if (!this.isModified('username')) {
return next();
}
const total = await this.constructor.countUsersWithUsername(this.username);
if (total > 0) {
return next(new Error(`Username ${this.username} is already taken`));
}
return next();
});
UserSchema.pre('save', async function (next) {
if (!this.isModified('email')) {
return next();
}
const total = await this.constructor.countDocuments({ email: this.email });
if (total > 0) {
return next(new Error(`Email ${this.email} is taken`));
}
return next();
});
If 条件似乎是使用 Ramda 的好地方,我更改了我的代码
const total = await this.constructor.countUsersWithUsername(this.username);
const isUsernameTaken = R.ifElse(
R.gt(0),
() => next(),
() => next(new Error(`Username ${this.username} is already taken`))
);
return isUsernameTaken(total);
这行得通,但我开始考虑我可以将 IfElse 重构到一个不同的模块中,然后我需要传入 next 和一个标签,这样我就可以说 ${label} ${value} 已经被采用。
我将如何重构它?
Mongoose 也是基于 class 的,是否有功能库可以与 MongoDB 连接?
我不会费心用 Ramda 做这个。 Ramda 的 ifElse
偶尔很有用,但大多数时候并不值得。通常只需要一个条件表达式(三元)。请注意,我是 Ramda 的创始人和忠实粉丝;但我有很多时候现代 JS 也一样好,或者在这里,甚至更老的 JS。
这将是我的方法,而不是试图弄清楚如何在你的钩子中调用它:
const isTaken = (label) => (value, count, next) =>
count > 0
? next (new Error (`${label} ${value} is already taken`))
: next ()
const isUsernameTaken = isTaken('Username')
const isEmailTaken = isTaken('Email')
const next = (err) => {
console.log(err ? `${err}` : `Success`)
}
isUsernameTaken('Fred', 2, next);
isUsernameTaken('Wilma', 0, next);
isEmailTaken('fred@bedrock.com', 0, next)
isEmailTaken('wilma@stoneage.com', 1, next)
无论您是想要特定的助手 isUsernameTaken
和 isEmailTaken
还是只想调用通用的 isTaken
都将决定您是否应该柯里化第一个参数。应该很容易改变。