您如何 return mongodb 向浏览器发送 hapi.js 路由处理程序中的信息?

How do you return mongodb info to the browser inside a hapi.js route handler?

我刚刚开始使用 hapi.js (^17.3.1) 和 mongodb (^3.0.7),以及异步 js 代码。

在路由处理程序中,我正在尝试从数据库中检索数据。作为测试,我将一个字符串存储在一个变量 "s" 中,该变量是通过遍历数据库集合记录构建的。浏览器的预期输出是

start dbInfo1 dbInfo2 dbInfoN end

我试过此代码的各种版本:

module.exports = {
    method: 'GET',
    handler: async function (request, reply) { 
        return await getRoutes();
    }       
}

async function getRoutes() {

    var s = "start";
    const mongo = require('mongodb').MongoClient;
    const mongoUrl = "mongodb://127.0.0.1:27017/";

    return // I'm returning this whole thing because hapi.js says it wants a promise. (500 error)
        await mongo.connect(mongoUrl)
        .then(function(client) {

            client.db("dbName").collection("collectionName")
            .find({})
            .forEach(function (record) {
                console.log(record.item);
                s += " | " + record.item;      
            });

            s + " end";  // But I've tried placing "return" here (500 error)

        });
        // I've also tried ".then(function(s) { return s + 'end' }) here but it seems to only have the same set of options/problems manifest.

        // I've also made it so that I place "return s + 'end'" here (displays "start end" with nothing in the middle).

}

我试过将 return 语句放在不同的地方。我要么在控制台中收到 http 500 错误

Debug: internal, implementation, error
Error: handler method did not return a value, a promise, or throw an error
dbInfo1
dbInfo2
dbInfoN

如果我 return 承诺本身或来自承诺内部,或者我得到

start end

在浏览器中,如果我 return 来自 promise 之外。

在任何一种情况下,console.log 语句都会打印出 dbInfos 输出。

我尝试了 async 和 await 的不同放置、包含和省略,结果几乎相同。我还尝试使用 "new Promise(..." 将 getRoutes 中正在 returned 的内容包装到显式 Promise 中。在这种情况下,控制台会记录 dbInfos,但浏览器会挂起。

如何在 return 变量 s 之前等待 "foreach" 函数?

未经测试,我可以说这是错误的:

return // I'm returning this whole thing because hapi.js says it wants a promise. (500 error)
    await mongo.connect(mongoUrl)
    .then(function(client) {

        client.db("dbName").collection("collectionName")
        .find({})
        .forEach(function (record) {
            console.log(record.item);
            s += " | " + record.item;      
        });

        s + " end";  // But I've tried placing "return" here (500 error)

    });

return 被解析为 return;

return await mongo.connect(mongoUrl)
    .then(function(client) {

        client.db("dbName").collection("collectionName")
        .find({})
        .forEach(function (record) {
            console.log(record.item);
            s += " | " + record.item;      
        });

        s + " end";  // But I've tried placing "return" here (500 error)

    });

是正确的方法。任何 linter 都会警告你。

终于!使用此代码得到它:

module.exports = {
    method: 'GET',
    handler: function (request, reply) { 
        return getRoutes();
    }
}

function getRoutes() {

    const mongo = require('mongodb').MongoClient;
    const mongoUrl = "mongodb://127.0.0.1:27017/";

    return mongo.connect(mongoUrl)
        .then(async function(client) {

            var s = "start";

            var documents = await 
                client.db("dbName").collection("collectionName")
                .find()
                .toArray();

            for (const doc of documents) 
                s += " | " + await doc.item;      

            return s + " end";

        });

}

问题是我认为由于 "getRoutes" 被标记为 "async",“.then” 中的内容也是异步的。但我确实需要将 "function(client)" 标记为 "async"。我还需要停止使用 "forEach" 并在集合上使用更传统的迭代。

我之前其实把"function(client)"标记为"async",但那是盲目的试错,所以一直没用好"await"。直到阅读 this Anton Lavrenov 的博客,我才真正开始理解它。

虽然我最近才问这个问题,但在那之前我已经研究了很长时间了。对我现在所处的位置真的很满意。当然,感谢@desoares 指出我在上面使用的代码版本中的愚蠢错误。