1

我需要遍历电子邮件列表并检查它们是否有效。如果验证失败,我会抛出一个错误让 Mocha 知道。

it('validates valid email addresses', function (done) {
  [
    'oliverash@me.com',
    'oliver.ash@me.com',
    'oliver-ash@me.com',
    'oliver+ash@me.com',
    'oliver\'s-email@me.com'
  ].forEach(function (value) {
    user.email = value

    user.validate(function (err) {
      // Failed to validate, throw an error
      if (err) {
        throw new Error()
      }
    })
  })

  // All documents validated, so call `done`
  done()
})

然而,这段代码似乎不能正常工作——如果数组中的最后一封电子邮件无效,它就会失效。

我究竟做错了什么?

4

2 回答 2

3

您可以使用async实用程序库来简化执行异步循环。

it('validates valid email addresses', function (done) {
  async.forEach([
    'oliverash@me.com',
    'oliver.ash@me.com',
    'oliver-ash@me.com',
    'oliver+ash@me.com',
    'oliver\'s-email@me.com'
  ], 
  function (value, callback) {
    user.email = value
    user.validate(callback)
  },
  function (err) {
    if (err) {
      throw new Error()
    }
    done()
  })
})

第一个函数在数组中的每个元素上调用,它有两个参数:数组中的项目和一个回调函数。如果回调收到错误,它会立即停止迭代。一旦数组中的所有项都完成(或其中任何一项都返回错误),就会调用最终函数。在这个例子中,它要么抛出错误,要么运行 Mocha done 函数。

async的自述文件很好地解释了 forEach 函数的工作原理。

于 2013-02-02T14:41:16.960 回答
1

如果您的user.validate函数是异步的,您的 forEach 调用将不会等待user.validate.

这意味着您的 forEach 函数将在user.validate调用所有回调done()之前结束,并将在每次验证结束之前调用。

您应该使用forEach函数的所有参数并done()user.validate回调中调用。我将添加一个计数变量来计数调用的回调并知道何时需要调用done()函数。

it('validates valid email addresses', function (done) {
  var count = 0;     // count variable
  [
    'oliverash@me.com',
    'oliver.ash@me.com',
    'oliver-ash@me.com',
    'oliver+ash@me.com',
    'oliver\'s-email@me.com'
  ].forEach(function (value, index, array) {
    user.email = value;

    user.validate(function (err) {
      ++count;      // Callback called, we add +1 to count.
      if (err) {
        throw new Error();
      }
      // Check if all callbacks have been called and call done if true.
      if (count === array.length)
        done();
    });

  });

})

这应该会更好。我没有测试它,但它应该可以工作。

PS:请不要忘记分号。在某些情况下,它会给你带来不确定的行为,不放它们是一个坏习惯(我们是程序员!)。

编辑 - 08/06/13:刚刚阅读了一些关于 Javascript 中分号的内容并记住了这个线程,这就是为什么你应该在你的代码中加入分号:http: //bonsaiden.github.io/JavaScript-Garden/#core.semicolon

于 2013-02-02T14:35:17.230 回答