这段Promise.all表单验证代码为何报TypeError?如何修复?
问题描述
我有一个包含多个表单的页面,每个表单对应独立的JavaScript文件,其中的验证方法如下:
function validateForm(){ return new Promise((resolve, reject) => { fetch(urls.validate) .then((r) => r.json()) .then((json) => { if (json.Success){ resolve("Complete!"); }else{ resolve(json.ErrorHtml); } }); }); }
页面加载时,我尝试把不同的验证方法存入数组,最初写法是:
var validationScripts = []; validationScripts.push("eisForm.validateForm();"); validationScripts.push("background.validateForm();");
当用户进入最后一个表单点击按钮时,需要执行所有验证脚本,我写了如下异步函数:
async function runValidation(){ const results = await Promise.all(validationScripts.map(script => script())); console.log(results); }
此时出现TypeError: script is not a function错误。我怀疑是方法后带了(),于是改成存储方法引用,但还是报相同错误。我需要实现所有Promise等待完成,并获取所有resolved值的集合。
更新后的示例代码:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title></title> </head> <body> <script> var test = test || {}; test.eisForm = (() => { async function validateForm(){ await fetch('https://jsonplaceholder.typicode.com/todos/1') .then((response) => response.json()) .then((json) => {return json;}); } return { validateForm: validateForm } })(); test.background = (() => { async function validateForm(){ await fetch('https://jsonplaceholder.typicode.com/todos/1') .then((response) => response.json()) .then((json) => {return json;}); } return { validateForm: validateForm } })(); var validationScripts = []; validationScripts.push(test.eisForm.validateForm); validationScripts.push(test.background.validateForm); async function runValidation(){ const results = await Promise.all(validationScripts.map(script => script())); console.log(results); } window.onload = function(){ runValidation(); } </script> </body> </html>
问题原因与修复方案
1. 初始写法的核心问题
最初你把字符串"eisForm.validateForm();"存入数组,执行script()时是在调用字符串,而字符串不是函数类型,必然触发TypeError。
2. 方法引用写法的隐藏问题
改成存储方法引用后仍有问题,看更新的示例代码,关键错误是**validateForm函数没有返回有效结果**:
async function validateForm(){ // 仅await了fetch流程,但没有返回最终数据 await fetch('https://jsonplaceholder.typicode.com/todos/1') .then((response) => response.json()) .then((json) => {return json;}); }
虽然async函数默认返回Promise,但内部await后未返回值,导致这个Promise最终resolve的是undefined;同时混用await和.then()的写法冗余,也容易引发逻辑疏漏。
3. 正确修复步骤
步骤1:修正validateForm的返回逻辑
简化写法并确保返回处理后的数据:
// test.eisForm为例,test.background同理修改 test.eisForm = (() => { async function validateForm(){ const response = await fetch('https://jsonplaceholder.typicode.com/todos/1'); const json = await response.json(); return json; // 返回最终数据,async自动包装为Promise } return { validateForm: validateForm } })();
步骤2:保持数组存储函数引用的正确写法
你更新代码里的这部分是对的,继续保留:
var validationScripts = []; validationScripts.push(test.eisForm.validateForm); validationScripts.push(test.background.validateForm);
步骤3:runValidation函数逻辑无需修改
现有写法可以正常实现需求:Promise.all会等待所有验证Promise完成,最终返回所有resolved值组成的数组:
async function runValidation(){ const results = await Promise.all(validationScripts.map(script => script())); console.log(results); // 输出两个待办事项对象组成的数组 }
4. 额外注意事项
- 如果原始业务中
fetch可能出现请求失败,建议在validateForm中添加try/catch捕获错误,避免单个验证失败导致整个Promise.all被reject; - 永远不要在数组中存储字符串形式的函数调用,直接存储函数引用才是正确的方式。
内容的提问来源于stack exchange,提问作者geoff swartz
相关产品推荐
相关产品推荐

