我试图找出一个很好的解决方案,用于从异步瀑布(异步库)函数中抽象出一个函数(以保持我的代码DRY),但我一直收到一个错误,说cb
是没有定义的。此外,仅将this
传递给bind
时,async
定义的函数是作用域,并且在传递cb
时也是如此。
最终,我找到了一个有效的解决方案(将cb
作为函数添加到this
对象),但它看起来有点乱,并且可能有更好的方法。有什么建议吗?:
// registerController.js
const async = require('async');
const registerService = require('../services/register');
// Api endpoint code
...
// is there a better way than (this.cb = cb)
let callbackHandler = (err, res) => {
if (err) this.cb(err);
this.cb(null, res);
};
// asynchronously perform registration
async.waterfall([
(cb) => {
registerService.createAccount(username, email, callbackHandler.bind(this.cb = cb));
},
(res, cb) => {
registerService.doSomethingElse(domain, callbackHandler.bind(this.cb = cb);
},
....
// registerService.js
module.exports = {
createAccount: (username, email, callback) => {
httpService.request({
host: myHost,
method: 'POST',
path: '/api/signup',
body: {
username,
email
}
}).then((res) => {
return callback(null, res);
}).catch((err) => {
return callback(err);
});
},
...
}
注意:代码重构为Services文件,用于单元测试和精益控制器(采用MVC方法)
答案 0 :(得分:0)
您不应该需要任何重构,async
已经是抽象的。只需删除callbackHandler
并将cb
直接传递到您的函数中:
async.waterfall([
(cb) => {
myService.createAccount(fullName, email, cb);
},
(res, cb) => {
myService.doSomethingElse(domain, cb);
},
…
], …);
但是,如果你在这里放弃async.js
并接受承诺,你会得到更简单的代码:
// registerController.js
const registerService = require('../services/register');
// Api endpoint code
…
registerService.createAccount(username, email)
.then(res =>
registerService.doSomethingElse(domain) // supposed to return a promise as well
)
…
// registerService.js
exports.createAccount = (username, email) => { // no callback
return httpService.request({
// ^^^^^^ returns the promise
host: myHost,
method: 'POST',
path: '/api/signup',
body: {
username,
email
}
});
};
…