Javascript 使用异步函数调用创建新承诺是一种错误的做法吗?

Javascript 使用异步函数调用创建新承诺是一种错误的做法吗?,javascript,node.js,mongodb,async-await,es6-promise,Javascript,Node.js,Mongodb,Async Await,Es6 Promise,代码段来自node.js和mongoDB CRUD应用程序。代码运行良好,但不确定我的结构和使用Promission和async Wait是否是错误的做法 handlers._newbies = {}; handlers._newbies.post = (parsedReq, res) => { const newbie = JSON.parse(parsedReq.payload); databaseCalls.create(newbie) .then

代码段来自node.js和mongoDB CRUD应用程序。代码运行良好,但不确定我的结构和使用Promission和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);
        }
    });
};
当节点服务器收到带有JSON负载的POST请求时,它会调用处理程序。_newbies.POST处理程序,该处理程序接受负载并将其传递给

const newbie = JSON.parse(parsedReq.payload);
databaseCalls.create(newbie)
打电话。我希望这个数据库调用返回一个承诺,该承诺包含
db.collection('newbies').insertOne(newbie)的结果
呼叫我在返回insertOne返回的承诺时遇到了麻烦,因为返回后我无法调用
client.close()


再说一次,也许我在这里做的很好,但我还没有在网上找到任何关于在承诺中创造承诺的东西。感谢您抽出时间让我知道我的问题中不清楚的地方。

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

而且,在您的例子中,您有几个错误处理问题

  • 如果在数据库代码中的任何地方出现错误,您永远不会解决或拒绝您正在创建的承诺。这是反模式的典型问题
  • 如果在打开数据库后出现错误,则不会关闭数据库
  • 您不会将错误反馈给呼叫方
  • 以下是如何在没有反模式和上述问题的情况下执行
    .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);
    });
    
    仅供参考,我还修改了一些其他内容:

  • 即使在出现错误的情况下,数据库连接也会关闭
  • 该函数返回一个承诺,该承诺由
    .insertOne()
    的结果解析(如果有有有意义的结果)
  • 如果存在错误,则返回的承诺将被该错误拒绝


  • 与您的承诺问题无关,但您通常不希望在每次操作中打开和关闭DB连接。您可以使用一个持久连接,也可以创建一个连接池,在其中可以从池中获取一个连接,然后在完成后将其放回池中(大多数数据库都具有这种类型的服务器端工作功能).

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

    而且,在您的例子中,您有几个错误处理问题

  • 如果在数据库代码中的任何地方出现错误,您永远不会解决或拒绝您正在创建的承诺。这是反模式的典型问题
  • 如果在打开数据库后出现错误,则不会关闭数据库
  • 您不会将错误反馈给呼叫方
  • 以下是如何在没有反模式和上述问题的情况下执行
    .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);
    });
    
    仅供参考,我还修改了一些其他内容:

  • 即使在出现错误的情况下,数据库连接也会关闭
  • 该函数返回一个承诺,该承诺由
    .insertOne()
    的结果解析(如果有有有意义的结果)
  • 如果存在错误,则返回的承诺将被该错误拒绝


  • 与您的承诺问题无关,但您通常不希望在每次操作中打开和关闭DB连接。您可以使用一个持久连接,也可以创建一个连接池,在其中可以从池中获取一个连接,然后在完成后将其放回池中(大多数数据库都具有这种类型的服务器端工作功能)。

    异步函数已经返回承诺。你为什么要这样做?你不应该用新的承诺来包装现有的承诺。这被认为是一种反模式,因为它完全没有必要。除了上述两个问题外,您还应该以不同的方式处理数据库连接。您正在为每个请求创建一个新连接。在启动时初始化连接并重用连接会更有效。谢谢您的回复。我想我是想得太多了。至于mongodb连接,您是说在应用程序启动时连接一次并一直保持打开状态是可以的吗?它最终是否会自行关闭连接,需要在将来请求时检查连接是否仍然存在或需要重新连接?我只是看一下mongoDB nodejs驱动程序文档,它显示了每个数据库交互的打开和关闭。再次感谢您的帮助。异步函数已经返回了承诺。你为什么要这样做?你不应该用新的承诺来包装现有的承诺。这被认为是一种反模式,因为它完全没有必要。除了上述两个问题外,您还应该以不同的方式处理数据库连接。您正在为每个请求创建一个新连接。在启动时初始化连接并重用连接会更有效。谢谢您的回复。我想我是想得太多了。至于mongodb连接,您是说在应用程序启动时连接一次并一直保持打开状态是可以的吗?它最终是否会自行关闭连接,需要在将来请求时检查连接是否仍然存在或需要重新连接?我只是看一下mongoDB nodejs驱动程序文档,它显示了每个数据库交互的打开和关闭。再次感谢你的帮助。非常棒的回答。我也在努力按照其他人的建议去做,打开应用程序上的mongo连接,继续使用相同的连接。我想出的每一个办法都失败了。我可以将我的整个应用程序包装在mongoClient.connect中,但这似乎不对。我好像有点紧张