Skip to content

validate 的返回类型可能让人误会进而导致 Promise 无法得到解决 #18

@tonitrnel

Description

@tonitrnel

发现了一个可能引起误会的代码,我最开始是阅读的 async-validator 的代码,但这个仓库似乎没人维护于是放弃提 issue 了。发现这个 fork 有人维护,因此在这里提一下,我不清楚 AntDesign 的用户有没有遇到该问题,我是使用 ElementPlus 遇到的

原因

interface.ts#L60-L73

  asyncValidator?: (
    rule: InternalRuleItem,
    value: Value,
    callback: (error?: string | Error) => void,
    source: Values,
    options: ValidateOption,
  ) => void | Promise<void>;
  validator?: (
    rule: InternalRuleItem,
    value: Value,
    callback: (error?: string | Error) => void,
    source: Values,
    options: ValidateOption,
  ) => SyncValidateResult | void;

这里 asyncValidator validator 从类型看均可以返回 undefined

而在处理时,似乎没考虑到空返回

index.ts#L267-L296

        let res: ValidateResult;
        if (rule.asyncValidator) {
          res = rule.asyncValidator(rule, data.value, cb, data.source, options);
        } else if (rule.validator) {
          try {
            res = rule.validator(rule, data.value, cb, data.source, options);
          } catch (error) {
            console.error?.(error);
            // rethrow to report error
            if (!options.suppressValidatorError) {
              setTimeout(() => {
                throw error;
              }, 0);
            }
            cb(error.message);
          }
          if (res === true) {
            cb();
          } else if (res === false) {
            cb(
              typeof rule.message === 'function'
                ? rule.message(rule.fullField || rule.field)
                : rule.message || `${rule.fullField || rule.field} fails`,
            );
          } else if (res instanceof Array) {
            cb(res);
          } else if (res instanceof Error) {
            cb(res.message);
          }
        }
        if (res && (res as Promise<void>).then) {
          (res as Promise<void>).then(
            () => cb(),
            e => cb(e),
          );
        }

此处的 res 可能是 undefined 然而在下方的判断逻辑只有 truefalseArrayErrorPromise,这在使用 validator 时如果返回 undefined 会导致 promise 永远得不到解决。

这个 promise 创建于 asyncMapasyncSerialArray 触发

解决方案

如果可以我建议 asyncValidatorvalidator 的返回类型去掉 void 或添加一条针对 resundefined 或直接 else的判断逻辑

很奇怪以前用 AntDesign 似乎一次也没遇到过这个问题

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions