0

I am following this guide running-imperatively and trying to implement the sequential processing sample.

const validate = validations => {
  return async (req, res, next) => {
    for (let validation of validations) {
      const result = await validation.run(req);
      if (result.errors.length) break;
    }

    const errors = validationResult(req);
    if (errors.isEmpty()) {
      return next();
    }

    res.status(400).json({ errors: errors.array() });
  };
};

The only significant eslint error I can't get around is no-await-in-loop Here is the current state of my code

One of the differences from the above sample is I'm not sending res in this middleware; instead, it's passed on to next

const validate = (validations) => async (req, res, next) => {
  const validationPromises = [];

  // lodash function :)
  _.forEach(validations, (validation) => {
    const validationPromise = new Promise((resolve, reject) => {
      validation.run(req).then((result) => {
        if (result.errors.length) {
          reject('Error');
        } else {
          resolve();
        }
      });
    });
    validationPromises.push(validationPromise);
  });

  Promise.all(validationPromises).then(next).catch(next);
};

The issue that I see is even though I'm rejecting if the validation run has an error, all the validations are still executed.

I have ensured the reject is correctly called, but all the Promiss are still executed. I'd expect if any Promise within Promise.all was rejected, it would stop the execution of the rest of the Promises.

Here is how the validate middleware is called,

router.post(
  '/submit',
  validate([
    body('challenge')
      .notEmpty({ ignore_whitespace: true })
      .withMessage('Invalid request. Please try login again'),
    body('email').isEmail().withMessage('Please provide a valid email'),
    body('comment')
      .notEmpty({ ignore_whitespace: true })
      .withMessage('Please provide a valid comment'),
    body('tosChecked')
      .isBoolean()
      .withMessage('Please select Terms of service'),
  ]),
  (req, res, next) => {
   ...
  }
);

Thanks for any feedback.

vava044
  • 51
  • 8
  • "*The only significant eslint error I can't get around is no-await-in-loop*" - it's not an error, it's a warning, and since you **want** sequential processing, you should simply **ignore** or even better disable that annoying rule. The authors [even recommend that](https://eslint.org/docs/latest/rules/no-await-in-loop#when-not-to-use-it). – Bergi Apr 11 '23 at 20:33
  • Btw, [avoid the Promise constructor antipattern](https://stackoverflow.com/q/23803743/1048572) with `validationPromise`. "*I'd expect if any Promise within Promise.all was rejected, it would stop the execution of the rest of the Promises.*" - no. The whole point of starting the execution of all `validation.run()` calls in a loop, collecting the promises in an array, and then using `Promise.all` to wait until all are done, is to make them run concurrently - not what you want! And when an exception happens, you cannot stop the calls that were already made. – Bergi Apr 11 '23 at 20:41
  • @Bergi, well errors and warning from eslint are contextual to the user based on the configuration. Thanks for the link btw! – vava044 Apr 12 '23 at 21:10

0 Answers0