我需要遍历电子邮件列表并检查它们是否有效。如果一个人无法验证,我会抛出一个错误让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()
})
但是,此代码似乎无法正常工作 - 只有数组中的最后一封电子邮件无效才会失效。
我做错了什么?
答案 0 :(得分: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函数。
readme for async很好地解释了forEach函数的工作原理。
答案 1 :(得分: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