简体   繁体   English

使用Async Waterfall时绑定回调函数

[英]Binding a callback function when using Async Waterfall

I was trying for a while to figure out a good solution for abstracting a function from an async waterfall (async library) function (to keep my code DRY), but I kept getting an error saying that cb was not defined. 我试图找出一个很好的解决方案,用于从异步瀑布(异步库)函数中抽象出一个函数(以保持我的代码DRY),但我一直收到一个错误,说cb没有定义。 Also, when passing just this to bind , the function that async was defined in was the scope, and when passing cb as well. 此外,当传递this bind ,定义async的函数是作用域,并且当传递cb也是如此。 Eventually, I found a solution which works (adding cb as a function to the this object), but it looks a bit messy and there is probably a better way of doing it. 最终,我发现了一个有效的解决方案(将cb作为函数添加this对象中),但它看起来有点乱,并且可能有更好的方法。 Any suggestions?: 有什么建议么?:

// 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);
        });
    },
...
}

Note: code refactored into Services file for unit testing purposes and lean controllers (taking an MVC approach) 注意:代码重构为Services文件,用于单元测试和精益控制器(采用MVC方法)

You're not supposed to need any refactoring, async is already abstract. 你不应该需要任何重构, async已经抽象的了。 Just drop the callbackHandler and pass the cb directly into your function: 只需删除callbackHandler并将cb直接传递给您的函数:

async.waterfall([
    (cb) => {
        myService.createAccount(fullName, email, cb);
    },
    (res, cb) => {
        myService.doSomethingElse(domain, cb);
    },
    …
], …);

However, you get much simpler code if you just abandon async.js here and embrace promises: 但是,如果你只是放弃async.js并接受promises,你会得到更简单的代码:

// 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
        }
    });
};
…

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM