如何在 Yup.test 上设置超时?

how to do setTimeout on Yup.test?

我正在尝试验证地址:

  line1: Yup.string()
    .test(
      "Address Line 1 Validation Test",
      "Please enter valid Line 1 address",
      async (line1: string) => {
        let delayTimer = null;
        let isValid = false;
        const doSearch = () => {
          clearTimeout(delayTimer);
          delayTimer = setTimeout(async () => {
            const { data } = await axios.get<{ status: string }>(
              "https://maps.googleapis.com/maps/api/geocode/json?components=country:USA",
              {
                params: {
                  address: line1,
                  key: GEOCODE_API_KEY,
                },
              }
            );
            console.log("line1: ", line1);
            console.log("data: ", data);
            isValid = data.status === "OK" ? true : false;
          }, 1000); // Will do the ajax stuff after 1000 ms, or 1 s
        };
        doSearch();
        return isValid;
      }
    )
    .required("Line 1 is required"),

我想像这样集成延迟搜索,这样我就不会在每次用户输入时都淹没我的api:AJAX: Delay for search on typing in form field

但它会在每次用户输入时执行 api 请求。我该如何实施?

问题是您实际上从未清除超时。

每次您的处理程序运行时,都会创建并初始化新的 delayTimerisValiddoSearch 变量。这些变量必须放在外部范围内。像这样:

let delayTimer = null;
let isValid = false;

Yup.string()
    .test(
        'Address Line 1 Validation Test',
        'Please enter valid Line 1 address',
        async (line1: string) => {
            clearTimeout(delayTimer);
            
            delayTimer = setTimeout(async () => {
                const {data} =
                    (await axios.get) <
                    {status: string} >
                    ('https://maps.googleapis.com/maps/api/geocode/json?components=country:USA',
                    {
                        params: {
                            address: line1,
                            key: GEOCODE_API_KEY
                        }
                    });
                console.log('line1: ', line1);
                console.log('data: ', data);
                isValid = data.status === 'OK';
            }, 1000); // Will do the ajax stuff after 1000 ms, or 1 s
            
            return isValid;
        }
    )
    .required('Line 1 is required');

现在,即使这解决了您最初的问题,还有另一个问题需要解决。您的函数将始终 return 具有错误值 isValid 的承诺。

你必须做什么取决于你想要什么,但我会给你以下见解:

let delayTimer = null;
let isValid = false;
let resolveRef = null;

Yup.string()
    .test(
        'Address Line 1 Validation Test',
        'Please enter valid Line 1 address',
        async (line1: string) => {
            clearTimeout(delayTimer);

            if (resolveRef) {
                resolveRef(isValid);
                resolveRef = null;
            }

            return await new Promise((resolve) => {
                resolveRef = resolve;
                delayTimer = setTimeout(async () => {
                    const {data} =
                    (await axios.get) <
                    {status: string} >
                    ('https://maps.googleapis.com/maps/api/geocode/json?components=country:USA',
                        {
                            params: {
                                address: line1,
                                key: GEOCODE_API_KEY
                            }
                        });

                    isValid = data.status === 'OK';

                    resolve(isValid);
                    resolveRef = null;
                }, 1000);
            });
        }
    )
    .required('Line 1 is required');

希望它有效。请告诉我。