【问题标题】:NodeJs: Wait for ForEach functionNodeJs:等待 ForEach 函数
【发布时间】:2015-12-03 10:03:43
【问题描述】:

我编写了一个验证函数,我想检查一个数组是否可以插入。我想返回多个错误。 我搜索了该主题,但无法通过承诺异步模块运行它。 我对 NodeJS 很陌生,如果您能帮助我,我将不胜感激。

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); 在函数准备好返回之前返回 undefined。 非常感谢。

编辑: Promise Attempt(在第二个 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);
                            });

【问题讨论】:

    标签: javascript node.js


    【解决方案1】:

    问题在于Exercise.forge({name: req.body.name }).fetch(...),因为它异步运行,这使得validateNewResultUnits 函数继续执行,直到它返回未定义的结果。

    我建议您更改该代码以包含 Promise 而不是那些丑陋的异步回调,这将需要更改 validateNewResultUnits 函数本身及其任何调用者。这里有一些资源可以帮助你快速理解 Promise:

    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


    编辑

    这是所提供代码的副本,但使用了 Promise

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

    【讨论】:

    • 那么如果我使用 bluebird 来制作 Exercise.forge... 承诺该功能将同步?
    • 它不会让它同步,但它会向调用者返回一个promise,调用者可以附加一个.then(function(){...}),当promise被解决或拒绝时会调用它,像这样:var promise = asyncFetch(); promise.then(function success(result) {}, function error(error) {});
    • 如果您使用的是 nodejs,则基本 Promise 不需要 bluebird,它已经包含在内。
    • @ShanShan Bluebird 有很好的实用功能,例如 filtermapmapSerieseach,在替换 forEach 循环时可能很有用
    • 好的。但是我的问题。如果我将Exercise.forge.. 包装成一个承诺。 forEach 等待会起作用吗?
    猜你喜欢
    • 1970-01-01
    • 2021-06-21
    • 2016-10-29
    • 2020-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多