当 运行 mocha 单元测试时,如何避免我的 Q promise catch 块在 NodeJS 回调样式 API 中被调用两次?
How can I avoid my Q promise catch block being called twice in a NodeJS callback-style API when running mocha unit tests?
我们在节点 API 中使用 Q promise 库,但允许通过回调调用函数。
例如:
function foo(cb) {
Q.fcall(function () {
return true;
}).then(function (result) {
return cb(null, result);
}).catch(function (err) {
return cb(err, null);
});
}
当我 运行 我的 mocha 单元测试时,如果回调 中存在异常 ,则会导致回调被调用两次。
例如:
var called = 0;
foo(function (err, res) {
called++;
console.log('err: ' + err);
console.log('res: ' + res);
console.log('called: ' + called);
throw Error(throw Error from foo!');
});
结果如下:
err: null
res: true
called: 1
err: Error: throw Error from foo!
res: null
called: 2
我们发现的一种方法是执行以下操作:
function foo2(cb) {
var _result, _err;
Q.fcall(function () {
return true;
}).then(function (result) {
_result = result;
}).catch(function (err) {
_err = err;
}).finally(function () {
_.defer(cb, _err, _result);
});
}
我们的想法是在一个地方调用回调,并通过强制延迟清除调用堆栈来尝试防止开发人员错误。
使用这种方法,我们的回调被调用一次,任何错误(或者在我们的例子中,断言)都由调用者直接处理。
我们可以使用更好的技术吗?我觉得这是一个很常见的场景,所以我想有一个更干净的解决方案...
修改您的 foo
函数以使用 2 个单独的处理程序在同一个 then
调用中处理履行和拒绝:
function foo(cb) {
Q.fcall(function () {
return true;
}).then(function (result) {
return cb(null, result);
}, function (err) {
return cb(err, null);
});
}
我们在节点 API 中使用 Q promise 库,但允许通过回调调用函数。
例如:
function foo(cb) {
Q.fcall(function () {
return true;
}).then(function (result) {
return cb(null, result);
}).catch(function (err) {
return cb(err, null);
});
}
当我 运行 我的 mocha 单元测试时,如果回调 中存在异常 ,则会导致回调被调用两次。
例如:
var called = 0;
foo(function (err, res) {
called++;
console.log('err: ' + err);
console.log('res: ' + res);
console.log('called: ' + called);
throw Error(throw Error from foo!');
});
结果如下:
err: null res: true called: 1 err: Error: throw Error from foo! res: null called: 2
我们发现的一种方法是执行以下操作:
function foo2(cb) {
var _result, _err;
Q.fcall(function () {
return true;
}).then(function (result) {
_result = result;
}).catch(function (err) {
_err = err;
}).finally(function () {
_.defer(cb, _err, _result);
});
}
我们的想法是在一个地方调用回调,并通过强制延迟清除调用堆栈来尝试防止开发人员错误。
使用这种方法,我们的回调被调用一次,任何错误(或者在我们的例子中,断言)都由调用者直接处理。
我们可以使用更好的技术吗?我觉得这是一个很常见的场景,所以我想有一个更干净的解决方案...
修改您的 foo
函数以使用 2 个单独的处理程序在同一个 then
调用中处理履行和拒绝:
function foo(cb) {
Q.fcall(function () {
return true;
}).then(function (result) {
return cb(null, result);
}, function (err) {
return cb(err, null);
});
}