javascript - 使用异步函数调用创建新的 Promise 是不好的做法吗?

标签 javascript node.js mongodb async-await es6-promise

代码片段来自node.js 和mongoDB CRUD 应用程序。 Github repo for full code.代码工作正常,但不确定我的结构以及 Promise 和 async wait 的使用是否是不好的做法。

handlers._newbies = {};

handlers._newbies.post = (parsedReq, res) => {

    const newbie = JSON.parse(parsedReq.payload);
    databaseCalls.create(newbie)
        .then((result) => {
            res.writeHead(200,{'Content-Type' : 'application/json'});
            const resultToString = JSON.stringify(result.ops[0]);
            res.write(resultToString);
            res.end();
        })
        .catch(err => console.log(err));
};


const databaseCalls = {};

databaseCalls.create = (newbie) => {
    return new Promise(async (resolve, reject) => {
        try {
            const client = await MongoClient.connect('mongodb://localhost:27017', { useNewUrlParser: true });
            console.log("Connected correctly to server");
            const db = client.db('Noob-List');
            const result = await db.collection('newbies').insertOne(newbie);
            client.close();
            resolve(result);
        } catch(err) {
            console.log(err);
        }
    });
};

当 Node 服务器收到带有 JSON 有效负载的 POST 请求时,它会调用 handlers._newbies.post 处理程序,该处理程序获取有效负载并将其传递给

const newbie = JSON.parse(parsedReq.payload);
databaseCalls.create(newbie)

打电话。我希望此数据库调用返回一个包含 db.collection('newbies').insertOne(newbie); 结果的 promise 称呼。我在仅返回 insertOne 返回的 promise 时遇到了麻烦,因为返回后我无法调用 client.close(); .

也许我在这里所做的一切都很好,但我没有在网上找到任何关于使用其中的 promise 创建 promise 的内容。感谢您抽出宝贵的时间让我知道我的问题中有哪些不清楚的地方。

最佳答案

将现有的 Promise 包装在手动创建的 Promise 中被认为是一种反模式,因为没有理由这样做,而且它会产生许多错误的机会,特别是在错误处理中。

并且,就您的情况而言,您有几个错误处理问题。

  1. 如果您的数据库代码中的任何位置出现错误,您永远不会解决或拒绝您正在创建的 promise 。这是反模式的典型问题。
  2. 如果打开数据库后出现错误,则不要关闭数据库
  3. 您不会向调用者返回错误。

以下是如何在没有反模式且没有上述问题的情况下执行 .create() 函数:

databaseCalls.create = async function(newbie) {
    let client;
    try {
        client = await MongoClient.connect('mongodb://localhost:27017', { useNewUrlParser: true });
        console.log("Connected correctly to server");
        const db = client.db('Noob-List');
        return db.collection('newbies').insertOne(newbie);
    } catch(err) {
        // log error, but still reject the promise
        console.log(err);
        throw err;
    } finally {
        // clean up any open database
        if (client) {
            client.close();
        }
    }
}

然后,您可以像这样使用它:

databaseCalls.create(something).then(result => {
    console.log("succeeded");'
}).catch(err => {
    console.log(err);
});

仅供引用,我还修改了其他一些内容:

  1. 即使在错误情况下,数据库连接也会关闭
  2. 该函数返回一个 Promise,该 Promise 通过 .insertOne() 的结果进行解析(如果那里有有意义的结果)
  3. 如果出现错误,则返回的 Promise 会因该错误而被拒绝
<小时/>

与您的 promise 问题不是特别相关,但您通常不希望在每个操作上打开和关闭数据库连接。您可以使用一个持久连接,也可以创建一个连接池,您可以从池中获取一个连接,然后在完成后将其放回池中(大多数数据库都具有用于服务器端工作的此类功能)。

关于javascript - 使用异步函数调用创建新的 Promise 是不好的做法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50554373/

相关文章:

node.js - Nodejs如何处理多张图片上传

Spring MongoDB + QueryDSL 通过@DBRef 相关对象查询

mongodb - 如何使用Grails配置MongoDB

javascript - Angular 4 - IE11 : font-awesome is not working with angular2-multiselect-dropdown on IE11

javascript - 无法从特定选择中获取选项

javascript - 井字游戏循环

php - 用于请求/跟踪功能或错误的 Azure DevOps 自定义页面

mongodb - Spring data Mongodb bulk save continue on error

javascript - jquery slider 不显示

javascript - 流 : Cannot get . .. 因为对象文字中缺少属性 ...