Я пытался какое-то время найти хорошее решение для абстрагирования функции из функции async waterfall (async library) (чтобы сохранить мой код 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);
});
},
...
}
Примечание: код реорганизован в файл служб для тестирования модулей и бережливых контроллеров (с использованием подхода MVC)
Вы не должны нуждаться в каком-либо рефакторинге, async
уже является абстрактным. Просто снимите callbackHandler
и передайте cb
прямо в вашу функцию:
async.waterfall([
(cb) => {
myService.createAccount(fullName, email, cb);
},
(res, cb) => {
myService.doSomethingElse(domain, cb);
},
…
], …);
Однако вы получаете гораздо более простой код, если вы просто async.js
от async.js
здесь и 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
}
});
};
…
cb
- это функция с двумя параметрами, и это все, что требуется.