如何使用 Node js 在单个 API 调用中传递两个请求 - Cloudant

How to pass two requests in single API call with Node js - Cloudant

我试图在单个 API 调用中传递两个搜索请求,但有时我会同时获得两个请求结果,有时我只会获得一个请求结果。 基本上这是我在 cloudant db 中的 JSON 结构:

{
    "_id": "123",
    "name": "Naveen",
    "hoby": "Cricket"
},
{
    "_id": "234",
    "name": "Varun",
    "hoby": "chess"
},
{
    "_id": "345",
    "name": "Tarun",
    "hoby": "Cricket"
},
{
    "_id": "456",
    "name": "pavan",
    "hoby": "chess"
}

这里我的要求是 'hoby' 的板球 50 名成员和 'hoby' 的国际象棋 50 名成员。 为此,这就是我目前正在尝试的方式:

doGet: function(request, response) {
    var usersState = [];
    var names = { "usersState": usersState, "message": "ok" };
    if (!myDb) {
        response.json({ "message": "Dataabase connection failed" });
        return;
    }
    var queryForCricket = {
        "selector": {
            "hoby": "Cricket"
        },
        "fields": [
            "_id",
            "name",
            "hoby"
        ],
        "sort": [],
        "limit": 50,
        "skip": 0
    };
    var queryForChess = {
        "selector": {
            "hoby": "chess",
        },
        "fields": [
            "_id",
            "name",
            "hoby"
        ],
        "sort": [],
        "limit": 50,
        "skip": 0
    };
    async.parallel(
        [
            myDb.find(queryForCricket, function (err, body) {
                if (!err) {
                    body.docs.forEach(function (doc) {
                        if (doc)
                            usersState.push(doc);
                    });
                    response.json(names);
                }
            }),
            myDb.find(queryForChess, function (err, body) {
                if (!err) {
                    body.docs.forEach(function (doc) {
                        if (doc)
                            usersState.push(doc);
                    });
                }
            })
        ], function (err, results) {
            if (err) {
                response.send({ "message": "Read operration failed" });
                return;
            }
        });
}

我已经编写了两个查询并通过异步调用传递了两个,但始终无法正确获得结果。那么有没有优化的方式来处理查询部分和获取结果。

这里的问题是您的最终结果取决于 async.parallel find 函数的两个回调的执行顺序。当第二个 find 首先完成时,您将获得两个结果,但当第一个 find 首先完成时,您将仅获得 queryForCricked 查询的结果。

要获得这两个结果,您应该在最终回调函数中收集它们并在其中使用 response.json

...
 async.parallel(
    [
        myDb.find(queryForCricket, function (err, body) {
            if (!err) {
                body.docs.forEach(function (doc) {
                    if (doc)
                        usersState.push(doc);
                });
            }
        }),
        myDb.find(queryForChess, function (err, body) {
            if (!err) {
                body.docs.forEach(function (doc) {
                    if (doc)
                        usersState.push(doc);
                });
            }
        })
    ], function (err, results) {
        if (err) {
            response.send({ "message": "Read operration failed" });
            return;
        }

        response.json(names);
    }
);
...

虽然在共享 usersState 数组中收集数据是完全可行的方法,但它存在缺陷。例如,您无法控制 find 数据的插入顺序。 async.parallel 提供了一种更好的方法来从 运行 的函数中收集数据。您可以使用 callback async.parallel inserts 到每个函数中以在最终回调中收集数据:

async.parallel(
    [
        function (cb) { myDb.find(queryForCricket, cb); },
        function (cb) { myDb.find(queryForChess, cb); },
    ], function (err, results) {
        if (err) {
            response.send({ "message": "Read operration failed" });
            return;
        }
 
        // result is an array with data from queries: [crickets.body, chess.body]
        results.forEach(function (body) {
            body.docs.forEach(function (doc) {
                if (doc) usersState.push(doc);
            });
        });

        response.json(names);
    }
);
...