Not able to use array.every() correctly and getting wrong result

166 views Asked by At

I am trying to validate an array of Ids, for validation I am using custom validator in nestjs project. I am passing the array of ids in a callback function to my service class to query from the database whether id exists in the table or not and returns a boolean value. Every time I am receiving boolean true even if I am passing the wrong id.

Here is the validation function in a custom validator

import { ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments, registerDecorator, ValidationOptions } from "class-validator";
import { DeviceService } from "../device/device.service";
import { Injectable } from "@nestjs/common";


@ValidatorConstraint({ async: true })
@Injectable()
export class DevicesArrayValidatorConstraint implements ValidatorConstraintInterface {

    constructor(private deviceService: DeviceService) { }

    async validate(devices: Array<number>, args: ValidationArguments) {
        let result = devices.every(async (deviceId) => await this.deviceService.validateDevice(deviceId));
        if(result){
            return true;
        }
        else{
            return false;
        }
    }

    defaultMessage(args: ValidationArguments) { // here you can provide default error message if validation failed
        return "Here is an error";
    }

}

export function ValidDevices(validationOptions?: ValidationOptions) {
    return function (object: Object, propertyName: string) {
        registerDecorator({
            target: object.constructor,
            propertyName: propertyName,
            options: validationOptions,
            validator: DevicesArrayValidatorConstraint
        });
    };
}

Its the function from Service Class

async validateDevice(deviceId: number) {
  try {
    let result = await this.deviceRepository.findOneOrFail(deviceId)
    if(result){
      console.log(`In try block,This is id ${  deviceId}`)
    }
  } catch (error) {
    return false;
  }
  return true;
}

If I am passing an array of devices: [1,4], where 1 is valid and 4 is invalid. I am getting a double boolean result if I console.log() the return value.

attaching the console message enter image description here

1

There are 1 answers

7
T.J. Crowder On BEST ANSWER

every doesn't understand async functions. It just sees the promise that's returned as a truthy value.

You have a couple of options:

If you want to validate all of the devices in parallel, then check the result:

const validityFlags = await Promise.all(devices.map(deviceId => this.deviceService.validateDevice(deviceId)));
let result = validityFlags.every(Boolean);

Or if you want to validate each device in series, not bothering with later ones if you know an earlier one is invalid:

let result = true;
for (const deviceId of devices) {
    const valid = await this.deviceService.validateDevice(deviceId);
    if (!valid) {
        result = false;
        break;
    }
}