2015-12-03 28 views
0

Я пишу функцию проверки, где я хочу проверить, действителен ли массив для установки. Я хочу вернуть несколько ошибок. Я искал эту тему, но не смог ее запустить с обещаниями, асинхронным модулем. Im очень новичок в NodeJS и был бы очень благодарен, если бы вы могли мне помочь.NodeJs: Подождите, пока функция ForEach

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) { 
    // ... 
} 

console.log(validate); возвращение неопределенное перед функцией готово вернуть что-то. Большое спасибо.

EDIT: Promise Покушение (внутри второго 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); 
          }); 

ответ

3

Проблема заключается в Exercise.forge({name: req.body.name }).fetch(...), как она работает в асинхронном режиме, что делает функция validateNewResultUnits продолжает выполнение, пока она возвращает неопределенный результат.

Я предлагаю вам изменить этот код, чтобы использовать обещания вместо этих уродливых асинхронных обратных вызовов, которые потребуют изменений в самой функции validateNewResultUnits и любых ее вызывающих абонентов. Вот некоторые ресурсы, которые помогут вам понять обещания очень быстро:

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

Вот копия предоставленного кода, но с использованием вместо обещаний

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) { 
    // ... 
    } 
}); 
+0

Так что, если я использую Блюберд сделать '' Exercise.forge ... обещая функция будет синхронизироваться? – orgertot

+0

Он не будет синхронизироваться, но он вернет обещание вызывающему, и вызывающий может присоединить '.then (function() {...})', который будет вызываться, когда обещание будет устранено или отклонено , примерно так: '' var prom = asyncFetch(); prom.then (функция success (result) {}, function error (error) {}); '' – mkinawy

+1

Если вы используете nodejs, вам не нужна синяя птица для базового обещания, она уже включена. – Shanoor