我刚刚启动了一个新的Web应用程序,我想在我的JavaScript中实现某种形式的contract'esque样式验证。我做了一些快速的谷歌搜索,并遇到了JsContact,但语法并不是我想到的。有人知道其他图书馆吗?
我在想我希望语法类似于
String.prototype.padLeft = function(c, width) {
Verify.value(c).isRequired().isNotNull().isChar();
Verify.value(width).isRequired().isNotNull().isNumber().greaterThan(0);
...
Verify.value(result).isNotNull();
return result;
};
虽然将我自己的库与我想要的语法/方法放在一起不会花费很长时间,但如果其他人已经完成了工作并且它足够接近,那么它将节省我一些时间。提前谢谢。
更新
直到今天下午我才有时间研究这个问题,所以我会再花几个小时来看看是否有人有任何建议。如果没有,我会发布我在某处创建的任何内容作为下面的答案供其他人参考,如果他们愿意的话。
我还考虑了一些有意义的API,我现在正在考虑像(人为的例子):
function searchUser(firstName, middleInit, lastName) {
Verify.value(firstName).isString().matching(/\w+/); // Must have value
Verify.value(middleInit).whenNotNull().isChar(); // May be null, but not undefined
Verify.value(lastName).isString().withMinimumLengthOf(2); // Must have value
...
}
function syncTime(serverTime, now) {
Verify.value(serverTime).isDate(); // Must have value.
Verify.value(now).whenDefined().isDate(); // May be undefined, but not null.
}
我当前的想法是容忍NULL或UNDEFINED值是非典型的(至少对我而言?),而不是明确指定值.isNotNull()你实际上会禁用.whenDefined()或。 whenNotNull()如上图所示。我可能会在UNDEFINED上使.whenNotNull()没有错误,但我认为NULL与UNDEFINED是一个重要的区别;我们会看到......所有其他方法都很典型......想法?评论
答案 0 :(得分:5)
鉴于没有人推荐任何现有的图书馆,或者我认为这是一个好主意我疯了,我继续把一个基本的图书馆拼凑起来。代码不是很花哨,但它可以实现我想要的,并且运行起来相当快(IE中每毫秒大约40个链式检查)。
我选择了最终语法,如:
function syncTime(serverTime, now) {
Verify.value(serverTime).always().isDate(); // Cannot be undefined or null.
Verify.value(now).whenDefined().isDate(); // Cannot be null, but must be date when defined.
//Code
}
function searchForUser(firstName, middleInit, lastName) {
Verify.value(firstName).always().isString().withMinimumLengthOf(2); // Cannot be undefined or null.
Verify.value(lastName).always().isString().withMinimumLengthOf(2); // Cannot be undefined or null.
Verify.value(middleInit).whenNotNull().isChar().between('A', 'Z'); // Cannot be undefined, but must be single char string when not null.
//Code
}
我通过.always()检查选择了一个明确的“必须有价值”,我个人觉得它更好阅读;但我可以看到一些另一种方式。
鉴于源代码超出了我想在此答案中发布的内容,如果您对源代码感兴趣,请转到此CodePlex Wiki Page。我想它转向更流畅的断言库;但它做了我需要的。
<强>更新强>
我在上面链接的CodePlex页面上更新了源代码。具体来说,我重构了Verify类以使用'值上下文',而不是总是构建新的Verifier对象;大大提高了IE的性能(从来不是FireFox或Chrome的问题)...现在在IE中每ms处理大约100个链式检查。
答案 1 :(得分:1)
我可能会建议您使用下一个代码合同库: dbc-code-contracts 。
NPM:https://www.npmjs.com/package/dbc-code-contracts
GitLab回购(主页):https://gitlab.com/o.oleg/orbios.dbc#README
使用单元测试进行CI构建:https://gitlab.com/o.oleg/orbios.dbc/-/jobs/
示例代码:
Dbc.Contract.throwException = true;
const domId = "my-div";
const div = document.createElement("div");
div.id . = domId;
document.body.appendChild(div);
const state = Dbc.Dom.removeById(domId);
Dbc.Contract.isTrue(state);
Dbc.Contract.isNull(document.getElementById(domId));
支持以下合同(2017年11月2日):
此外,还有来自此库的DOM方法内部合同检查。
答案 2 :(得分:0)
我也把我的类型合同的想法放在一起,这就是我想要的。我想,有点晚了,但我会建议那些愿意看的人:https://github.com/lindem/FirstContract
这是一个WIP,但我需要类似的东西。
function bmi (weight, height) {
return weight / height * height;
}
var c = require("firstcontract").c
/*
* contract applies to function taking two non-negative numbers,
* returning a negative number:
*/
, contract = c(["R+0", "R+0"], "R+0")
, cbmi = contract(bmi)
;
它被创建,以便我可以添加和删除它而不更改监视本身的功能,并提供围绕该功能的钳位。这是常见问题,而且是在npm。
答案 3 :(得分:0)
还有一个 - https://www.npmjs.com/package/bycontract 它是一个小型库,需要JSDoc表达式(http://usejsdoc.org/)来签订合同。您很有可能熟悉语法。
看到它的实际效果:
// Simple test
byContract( true, "boolean" ); // ok
// Multiple Types
byContract( 100, "string|number|boolean" ); // ok
// Optional Parameters
function foo( bar, baz ) {
byContract( arguments, [ "number=", "string=" ] );
}
这里有一个现实世界的例子:
/**
* @param {number|string} sum
* @param {Object.<string, string>} payload
* @param {function} cb
* @returns {HTMLElement}
*/
function foo( sum, payload, cb ) {
// Test if the contract is respected at entry point
byContract( arguments, [ "number|string", "Object.<string, string>", "function" ] );
// ..
var res = document.createElement( "div" );
// Test if the contract is respected at exit point
return byContract( res, HTMLElement );
}
// Test it
foo( 100, { foo: "foo" }, function(){}); // ok
foo( 100, { foo: 100 }, function(){}); // exception - ByContractError: Value of index 1 violates the contract `Object.<string, string>`