orgertot
orgertot

Reputation: 197

NodeJs: Wait for ForEach function

I write a validate function where I want to check if a array is valid to be instert. I want to return multiple errors. I searched for that topic but couldnt get it runnig with promises, async-module. Im very new to NodeJS and would be very grateful if you could help me.

function validateNewResultUnits(sets, req) {
  var validate = [];
  sets.forEach(function(setItem) {
    setItem.forEach(function(item) {
      if (item.hasOwnProperty("name") == false) {
        validate.push({
          'name': 'Name has to be set'
        });
      } else {
        if (item.name === "" || item.name === null || item.name === undefined) {
          validate.push({
            'name': 'Name cannot be empty'
          });
        } else {
          Exercise.forge({
            name: req.body.name
          }).fetch({
            withRelated: [{
              'resultUnits': function(qb) {
                qb.where('name', item.name);
              }
            }]
          }).then(function(exercise) {
            console.log("Länge:" + exercise.related('resultUnits').length);
            if (exercise.related('resultUnits').length === 0)
              validate.push({
                'name': 'ResultUnit not found'
              });
          }).catch(function(error) {
            validate.push({
              'name': 'An Error occured'
            });
          });
        }
      }

      if (item.hasOwnProperty("value") == false) {
        validate.push({
          'value': 'Value has to be set'
        });
      } else {
        if (item.value === "" || item.value === null || item.value === undefined) {
          validate.push({
            'value': 'Name cannot be empty'
          });
        } else {
          if (isNaN(item.value)) validate.push({
            'value': 'Value has to be number'
          });
        }
      }
    });
  });
  return validate;
}

var validate = validateNewResultUnits(req.body.sets, req);
console.log(validate);
if (validate.length == 0) {
  // ...
}

The console.log(validate); return undefined before the function is ready to return something. Thanks a lot.

EDIT: Promise Attempt (inside the second forEach)

var promise = new Promise(function(resolve) {
                                Exercise.forge({name: req.body.name })
                                .fetch({
                                    withRelated: [{'resultUnits': function(qb) {
                                        qb.where('name',item.name)
                                    }}]
                                }).then(function(exercise) { 
                                console.log("Länge:"+exercise.related('resultUnits').length);
                                if (exercise.related('resultUnits').length === 0)
                                    resolve({'name':'ResultUnit not found'});
                                }).catch(function(error) { resolve({'name': 'An Error occured'}); });
                            });
                            promise.then(function(result) {
                                validate.push(result);
                            });

Upvotes: 0

Views: 1186

Answers (1)

mkinawy
mkinawy

Reputation: 375

The problem is in Exercise.forge({name: req.body.name }).fetch(...) as it runs asynchronously which makes the validateNewResultUnits function continues its execution till it returns undefined result.

I would suggest that you change that code to embrace promises instead of those ugly async callbacks, that will require changes in the validateNewResultUnits function itself and any of its callers. Here is some resources that will help you understand promises very quickly:

https://strongloop.com/strongblog/promises-in-node-js-with-q-an-alternative-to-callbacks/

Understanding promises in node.js

http://howtonode.org/promises

https://vimeo.com/144550711

https://vimeo.com/144550811

https://vimeo.com/144550913


EDIT

Here is a copy of the provided code but using promises instead

function validateNewResultUnits(sets, req) {
  return new Promise(function(resolve, reject){
    var validate = [];
    var internalPromises = [];
    sets.forEach(function(setItem) {
      setItem.forEach(function(item) {
        if (item.hasOwnProperty("name") == false) {
          validate.push({'name': 'Name has to be set'});
        } else {
          if (item.name === "" || item.name === null || item.name === undefined) {
            validate.push({'name': 'Name cannot be empty'});
          } else {
            var internalPromise = Exercise.forge({name: req.body.name}).fetch({
                withRelated: [{
                  'resultUnits': function (qb) {
                    qb.where('name', item.name);
                  }
                }]
              });
            internalPromise.then(function(exercise) {
              console.log("Länge:" + exercise.related('resultUnits').length);
              if (exercise.related('resultUnits').length === 0)
                validate.push({'name': 'ResultUnit not found'});
            }).catch(function(error) {
              validate.push({'name': 'An Error occured'});
            });
            internalPromises.push(internalPromise);
          }
        }

        if (item.hasOwnProperty("value") == false) {
          validate.push({'value': 'Value has to be set'});
        } else {
          if (item.value === "" || item.value === null || item.value === undefined) {
            validate.push({'value': 'Name cannot be empty'});
          } else {
            if (isNaN(item.value))
              validate.push({'value': 'Value has to be number'});
          }
        }
      });
    });

    if(internalPromises && internalPromises.length) {
      Promise.all(internalPromises).then(function (value) {
        console.log(value);
        resolve(validate);
      }, function (reason) {
        console.log(reason);
        resolve(validate);
      });
    } else {
      resolve(validate);
    }
  });
}

var validatePromise = validateNewResultUnits(req.body.sets, req);
validatePromise.then(function(result){
  console.log(result);
  if (result.length == 0) {
    // ...
  }
});

Upvotes: 3

Related Questions