-1

I have a page made up of multiple forms. Each form has it's own javascript file with a validate method like so.

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);
                    }
                });
        });
    }

When the page loads, it loads up an array of the different javascript file methods to call like this.

var validationScripts = [];
validationScripts.push("eisForm.validateForm();");
validationScripts.push("background.validateForm();");

Finally, when the user gets to the last form the button needs to run all of the validation scripts.

async function runValidation(){
    const results = await Promise.all(validationScripts.map(script => script()));
    console.log(results);
}

This gives a TypeError: script is not a function error. I wasn't sure if it might be because each validateForm is followed by () and then in the map method it uses () again. I tried removing them from the array's push of each validateForm but I still get the same error.

I'm not sure how to make this work so that all of the Promises are awaited and the results const is a collection of all the resolved values.

Update

Here's an example.

<!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>
2
  • 4
    It's an array of strings, not of functions. Also why in the first function do you wrap fetch, which already returns a promise, in a new Promise?! Commented Apr 22 at 18:13
  • Avoid the Promise constructor antipattern! Commented Apr 22 at 22:22

1 Answer 1

2

TypeError: script is not a function

That's because it's a string, since you're adding strings to that array:

validationScripts.push("eisForm.validateForm();");
validationScripts.push("background.validateForm();");

It sounds like your intent is to add the functions themselves:

validationScripts.push(eisForm.validateForm);
validationScripts.push(background.validateForm);

Note that there are no () parentheses to invoke the functions, what you're pushing onto the array is just a reference to the function itself. That reference can then be invoked as your later code expected.


Unrelated, but...

fetch() already returns a Promise, so there's no need to wrap it in another one. Your function can be simplified to just return the result from fetch():

function validateForm(){
  return fetch(urls.validate)
    .then((r) => r.json())
    .then((json) => {
      if (json.Success){
        return "Complete!";
      }else{
        return json.ErrorHtml;
      }
    });
}
Sign up to request clarification or add additional context in comments.

7 Comments

Doh! Of course. That's all getting me further, however, the value of results in the main function that calls Promise.All is [undefined]. Any idea why that would be? If I console.log(json) it does log the expected json with Success = true.
@geoffswartz: That sounds like a potentially separate issue, and one that would at least need a minimal reproducible example to demonstrate. It could depend on what those functions return, what the callback to Promise.all returns, what that function does with that result, etc.
I added to the original post, trying to throw something together that was basically doing the same thing.
@geoffswartz: That's an unrelated issue, and searching the error message leads here to start. In short, await can only be used in an async function (or at the top level of a module).
Ok, so removing the await from before runValidation essentially reproduced the earlier problem of getting undefined back from the validateForm methods.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.