1

Having a validation function, in this function there are three calls to asynchronous functions that execute independent conditions of the validation process, these asynchronous functions return the following object:

{status: true|false, message: void|string}

status is set to true if the validation in turn is successfully otherwise it is set to false and a message is added.

The requirement is: The validator function must return early, that is, if any asynchronous validation fails, it must stop there and return the reason for the failure in the object.

I attach an emulation of the implementation using callbacks because I can not use async/await:

function validator() {
    validation1(response => {
        if (response.status === false) {
            console.log('Here in validation1 validator needs to return response');
        }
    });

    validation2(response => {
        if (response.status === false) {
            console.log('Here in validation2 validator needs to return response');
        }
    });

    validation3(response => {
        if (response.status === false) {
            console.log('Here in validation3 validator needs to return response');
        }
    });
}

function validation1(callback) {
    setTimeout(() => {
        const object = {
            status: random(),
            message: 'message from validation 1'
        };

        callback(object);
    }, 2000);
}

function validation2(callback) {
    setTimeout(() => {
         const object = {
             status: random(),
             message: 'message from validation 2'
         };

         callback(object);
    }, 1000);
}

function validation3(callback) {
    setTimeout(() => {
         const object = {
             status: random(),
             message: 'message from validation 3'
         };

         callback(object);
    }, 3000);
}

// Helper function for generating random boolean
const random = () => Math.random() >= 0.5;

validator();

How can I notify the validator function that an error occurred and consequently return?

Thanks for your comments.

Regarding this question has already been answered in this question I think they do not address the same issue. One deals with synchronicity and asynchrony in javascript instead this question asks about how to handle sequential asynchronous functions and the strategy of how to handle when any of these functions fail.

Thanks to Paul's comment about error-first callback pattern I remember the article about callbacks in javascript.info. After reading I came to this solution.

function validatior() {
    validation1((error, success) => {
        if (error) {
            console.log(error.message);
        } else {
            validation2((error, success) => {
                if (error) {
                    console.log(error.message);
                } else {
                    validation3((error, success) => {
                        if (error) {
                            console.log(error.message);
                        } else {
                            console.log(success);
                        }
                    });
                }
            });
        }
    });
}

function validation1(callback) {
    setTimeout(() => {
        // callback(new Error('Error message from validation 1'));
        callback(null, true);
    }, 1000);
}

function validation2(callback) {
    setTimeout(() => {
        // callback(new Error('Error message from validation 2'));
        callback(null, true);
    }, 2000);
}

function validation3(callback) {
    setTimeout(() => {
        callback(new Error('Error message from vallidation 3'));
        // callback(null, true);
    }, 3000);
}

validatior();

This example will stop at validation3 stopping the validator process. I know this is looking like a callback hell, but there is in the same post an example about how to alleviate the problem.

Mario
  • 4,784
  • 3
  • 34
  • 50
  • Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – mpm Sep 23 '18 at 13:41
  • *i cannot use `async/await`* why though? – Jonas Wilms Sep 23 '18 at 13:47
  • just as a side-note, you're kind of breaking an expected pattern in Node. This kind of thing will often be done with an error-first callback pattern and if validation fails the error object is populated with that, otherwise it's null. If a passing validation needs to provide no info, then all you need is the null first parameter. – Paul Sep 23 '18 at 20:17
  • I am open to suggestions for better ideas to deal with this problem, in fact now I am looking for error-first callback pattern – Mario Sep 23 '18 at 20:21

1 Answers1

1

Instead of returning false you could return a promise that resolves on success and gets rejected when the validation fails, e.g.:

 const timer = ms => new Promise(resolve => setTimeout(resolve, ms));

 async function validate() {
   await timer(1000);
   if(/*isValid:*/ false) {
     throw new Error("Validation failed"); // rejection
  } else {
     return true; // resolve
 }
}

Then you can easily turn multiple promises into one:

 Promise.all([
   validate(),
   validate(),
   validate()
 ]).then(() => {
   // all fine
 }, error => {
   // at least one failed
   console.log(error.message);
 });
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
  • thanks for answering, could you please expand the answer in the context in which you validate () is an asynchronous function, I attach a jsfiddle https://jsfiddle.net/hqca570f/1/ – Mario Sep 23 '18 at 17:36
  • @user615274 you have to wrap the callback into a promise, edited – Jonas Wilms Sep 23 '18 at 20:12