首页 > 解决方案 > Node JS 中的架构与控制器、服务和存储库

问题描述

为了保持我的 node.js 的干净架构,我有控制器、服务和存储库。

数据流:控制器->服务->存储库->服务->控制器。在这个流程中(在简单的用户故事中),存储库将数据返回给服务,将服务返回给控制器。但是存储库应该处理对外部存储的请求。

现在我遇到了回调困难,如何在控制器和存储库之间实现嵌套回调?

我的控制器:

exports.clientes_get = async function (req, res) {

    Cliente.find(function(err,params) {
        if (err)
            res.send(err);

            res.json(params);
        });
}

我的服务:

 ClienteGet(req) {
        var response;

        repo.get(req.params.clienteId, (err, res) => {
            response = res;
            //console.log(response); -> have data
        });

        //console.log(response); -> doesnt have data
        return response;
    };

我的仓库:

get(clienteId, data) {
        mongoose.model('Cliente').findById(clienteId, data);
    };

我怎样才能做到这一点?

标签: node.jsservicecallbackrepositorydomain-driven-design

解决方案


Using Callbacks

If you insist on using callbacks:

Controller:

// notice that the `async` here was not necessary
exports.clientes_get = function (req, res) {
    // the `function(err, params) {...}` here is your callback
    ClienteGet(req, function(err, params) {
        if (err) {
            return res.send(err);
        }
        res.json(params);
    });
}

Service:

ClienteGet(req, callback) {
    // simply pass the callback argument directly to the `repo.get` call
    repo.get(req.params.clienteId, callback);
};

Repository:

get(clienteId, callback) {
    // again, just pass the callback here
    mongoose.model('Cliente').findById(clienteId, callback);
};

Using Promises

I personally recommend wrapping you code in Promises, because they are more flexible than callbacks, and modern JavaScript uses Promises heavily. It's pretty much the new standard... In fact, the async / await syntax is leveraging Promises under the hood.

Here's a rough sketch of how you could use Promises:

Controller:

exports.clientes_get = function (req, res) {
    return ClienteGet(req)
        .then((data) => {
            res.json(data);
        })
        .catch((err) => {
            res.send(err);
        });
}

Service:

ClienteGet(req) {
    return new Promise((resolve, reject) => {
        repo.get(req.params.clienteId, (err, res) => {
            if (err) {
                return reject(err);
            }
            resolve(res);
            //console.log(response); -> have data
        });
    });
};

Repository:

get(clienteId) {
    return new Promise((resolve, reject) => {
        mongoose.model('Cliente').findById(clienteId, function(err, document) {
            if (err) {
                return reject(err);
            }
            resolve(document);
        });
    });
};

推荐阅读