如何处理Node.js中的异步调用

时间:2018-09-07 19:15:09

标签: javascript node.js elasticsearch asynchronous

我是node.js的新手,我很难理解基于事件的异步编程的概念。 我正在实现一个宁静的API Web服务,因此请考虑以下简单的(同步!)API方法addStuff(),它将方法插入到Elasticsearch数据库中:

var client = new elasticsearch.Client({ host: 'localhost:9200' });

function indexStuff(stuff) {

    return client.index({
        index: 'test_idx',
        type: 'test',
        id: stuff.id,
        body: stuff
    });
}

function addStuff(req, res, next) {

    let stuff = processRequest(req);

    indexStuff(stuff).then(
        function (body) {
            return true;
        },
        function (error) {
            res.status(error.status).send({ message: error.message });
        }
    );
}

到目前为止,太好了。 现在在测试期间,我想避免将已经存在的东西插入数据库。 所以我想添加如下内容:

function stuffAlreadyInDB(id) {
    ... // returns true/false
}

function addStuff(req, res, next) {

    if (stuffAlreadyInDB(req.id))
    {
        res.status(409).send({ message: 'stuff with id ' + req.id + ' already in DB' });
        return;
    }

    var stuff = processRequest(req);

    ...
}

不幸的是,对elasticsearch db的调用是异步的,这意味着,我不能只在同步函数中返回布尔值。取而代之的是,我必须将整个shabang重构为这样的东西(可以说不太容易阅读):

function getStuffByID(id) {

    return client.get({
        id: id,
        index: 'test_idx',
        type: 'test',
        ignore: 404
    });
}

function addStuff(req, res, next) {


    getStuffByID(req.id).then(
        function(resp) {
            if (resp.found) {        
                res.status(409).send({ message: 'stuff with id ' + req.id + ' already in DB' });
                return;
            }
            else {
                var stuff = processRequest(req);
                indexStuff(stuff).then(
                    function (body) {
                        res.writeHead(200, {'Content-Type': 'application/json' });
                        res.end();
                    },
                    function (error) {
                        res.status(error.status).send({ message: error.message });
                    }
                );
            }
        },
        function(error) {

            res.status(error.status).send({ message: error.message });
        }

    );
}

至少,我还没有找到更好的解决方案。我试图找出如何使对数据库的异步调用成为同步调用,但基本上每个人都在说:只是不要这样做。 那么,如果我不想在测试完成后又想重构所有东西并对其进行重构,又该不再需要额外的数据库检查了,我该怎么做呢?

哦...,如果您对我的问题不满意,请发表评论。 因为我感觉很多人都在为这个问题而苦恼,但是我还没有找到满意的答案。

1 个答案:

答案 0 :(得分:1)

您可以使用async \ await语法使代码可读。 例如,您可以执行以下操作:

async function getStuffById(){
  //return true or false; }

在“添加内容”功能中,您可以编写:

if ( await getStuffById() ){
    //do some more stuff }

请注意,您还必须使“添加内容”异步,以便使用等待语法。

有关异步\ await的更多信息,请参见here