简体   繁体   English

如何使用异步 JS 验证器验证 HTML 表单

[英]How do I validate an HTML form using async JS validators

My question mentions an HTML form, but the crux of it pertains to how an arbitrary number of async JS functions can contribute to a single value – in the case of an HTML form, whether it's valid or not.我的问题提到了一个 HTML 表单,但它的症结在于任意数量的异步 JS 函数如何为单个值做出贡献——在 HTML 表单的情况下,它是否有效。

Being an old synchronous backend dinosaur, completely inexperienced with the use of JS promises/async-await, I can't seem to wrap my head around how to accomplish this.作为一个古老的同步后端恐龙,完全没有使用 JS promises/async-await 的经验,我似乎无法解决如何完成这个问题。

Consider this validation class:考虑这个验证 class:

class Validation {
    construct() {
        this.validators = [];
    }

    register(validator) {
        this.validators.push(validator);
    }

    validate(form) {
        let valid = true; // Benefit of the doubt
        this.validators.forEach(function(validator) {
            valid = validator(form) ? valid : false;
        });
        return valid;
    }
}

Say I want to register 3 validators:假设我想注册 3 个验证器:

const validation = new Validation();

validation.register(form => {
    // Return true if all required form fields have values, false otherwise
});

validation.register(form => {
    // Return true if the user has made any changes to the form, false otherwise
});

validation.register(form => {
    // Do an AJAX request and return true/false depending on the response
});

And then check to see if the form is valid, disabling or enabling its submit button accordingly:然后检查表单是否有效,相应地禁用或启用其提交按钮:

submitButton.setAttribute('disabled', !validation.validate(form));

All is fine for the first two validator functions, as they don't exhibit any asynchronous behavior.前两个验证器函数一切正常,因为它们没有表现出任何异步行为。 But the third validator function performs an AJAX call, and that is where it all falls apart.但是第三个验证器 function 执行 AJAX 调用,这就是一切崩溃的地方。

I assume the answer to the problem lies along the lines of re-writing the whole validate() method to somehow call the validator functions in an asynchronous manner.我认为问题的答案在于重写整个 validate() 方法以某种方式以异步方式调用验证器函数。 Ensuring that the submit button is enabled only if all the validators have returned true (in their sweet time) is what's really baking my noodle.确保只有在所有验证器都返回 true(在他们的甜蜜时光)时才启用提交按钮,这才是真正让我吃惊的原因。

Would someone be so kind as to magically transform my naive approach into something async friendly?有人会这么好心地将我天真的方法神奇地转变为异步友好的东西吗?

Just await the validators in a loop, and you can probably exit early once you find an error.只需循环等待验证器,一旦发现错误,您可能会提前退出。 Your function must become async .您的 function 必须变为async

Each validator can return a Promise<boolean> or just a boolean每个验证器都可以返回一个Promise<boolean>或仅返回一个boolean

async validate(form) {
    for (const validator of this.validators)
        if (!(await validator(form)) {
           return false;
        }
    }
    return true;
}

// Somewhere else
const isValid = await validation.validate(form);
submitButton.setAttribute('disabled', !isValid);

Note that you cannot do it with Array#forEach since it will not wait for each iteration if it returns a promise.请注意,您不能使用Array#forEach执行此操作,因为如果它返回 promise,它将不会等待每次迭代。 You also cannot return early from an Array#forEach您也不能从Array#forEach提前返回

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM