简体   繁体   中英

How to properly handle promise using nodejs and mongodb

I have configured my nodejs app to use mongodb. I can successfully connect and add data to my mongodb instance. My app is configured as follows (sensitive info is redacted):


// mongoDB configs
const MongoClient = require('mongodb').MongoClient;
const uri = "mongodb+srv://<username>:<password>@codigoinitiative.3klym.mongodb.net/<collection>?retryWrites=true&w=majority";
const client = new MongoClient(uri, { useNewUrlParser: true });

//express configs
const app = express();
const express = require('express');

//mongo endpoint
app.get('/mongo', (req, res) => {
    invoke().then(() => res.send('all good')).catch(err => console.log('invoke error:', err))
});


//mongodb access/logic
async function invoke() {
    console.log('connecting')

    return new Promise((resolve, reject) => {
        client.connect(err => {
            if(err) return reject(err)

            console.log('connected.');
            const collection = client.db("CodigoInitiative").collection("Registered");
            //create document to be inserted
            const pizzaDocument = {
            name: "Pizza",
            shape: "round",
            toppings: [ "Pepperoni", "mozzarella di bufala cheese" ],
            };
        
            // perform actions on the collection object
            const result = collection.insertOne(pizzaDocument);
            console.log(result.insertedCount);
        
            // //close the database connection
            client.close();
        });
    });

}

If I hit the /mongo endpoint, the pizza document is created on the database just fine, but I notice that the connection is never closed; meaning, the /node endpoint never sends the 'all good' string as a response. Also, any subsequent requests to /node then throw the following error:

connecting
the options [servers] is not supported
the options [caseTranslate] is not supported
the options [dbName] is not supported
the options [srvHost] is not supported
the options [credentials] is not supported
connected.
undefined
(node:94679) UnhandledPromiseRejectionWarning: MongoError: topology was destroyed
    at executeWriteOperation (/Users/vismarkjuarez/Documents/GitLab/CodigoInitiative/node_modules/mongodb/lib/core/topologies/replset.js:1183:21)
    at ReplSet.insert (/Users/vismarkjuarez/Documents/GitLab/CodigoInitiative/node_modules/mongodb/lib/core/topologies/replset.js:1252:3)
    at ReplSet.insert (/Users/vismarkjuarez/Documents/GitLab/CodigoInitiative/node_modules/mongodb/lib/topologies/topology_base.js:301:25)
    at insertDocuments (/Users/vismarkjuarez/Documents/GitLab/CodigoInitiative/node_modules/mongodb/lib/operations/common_functions.js:259:19)
    at InsertOneOperation.execute (/Users/vismarkjuarez/Documents/GitLab/CodigoInitiative/node_modules/mongodb/lib/operations/insert_one.js:26:5)
    at executeOperation (/Users/vismarkjuarez/Documents/GitLab/CodigoInitiative/node_modules/mongodb/lib/operations/execute_operation.js:77:17)
    at Collection.insertOne (/Users/vismarkjuarez/Documents/GitLab/CodigoInitiative/node_modules/mongodb/lib/collection.js:517:10)
    at /Users/vismarkjuarez/Documents/GitLab/CodigoInitiative/node.js:154:39
    at /Users/vismarkjuarez/Documents/GitLab/CodigoInitiative/node_modules/mongodb/lib/utils.js:677:5
    at /Users/vismarkjuarez/Documents/GitLab/CodigoInitiative/node_modules/mongodb/lib/mongo_client.js:226:7
(node:94679) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:94679) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

It appears I'm not handling the promise and async call correctly, and am missing a .catch() somewhere, but I'm not sure where. Where am I screwing up here?

The reason you're not seeing the all good is because this block

return new Promise((resolve, reject) => {

never actually resolves. You should resolve it by calling resolve(...) . Only then will your invoke().then(() =>... get triggered.

So I would make that block look something along these lines:

...
...
        
      // perform actions on the collection object
      const result = collection.insertOne(pizzaDocument);
      console.log(result.insertedCount);
        
      // //close the database connection
      client.close();
      resolve('ok')
...
...

But more generally, you certainly want the mongo connection be ready by the time a request comes in instead of opening up a new one every time.

Also, personally, I would simplify your code like so.

//mongo endpoint
app.get('/mongo', invoke);


//mongodb access/logic
const invoke = (req, res) => {
        client.connect(err => {
            if(err) return res.json(err)

            console.log('connected.');
            const collection = client.db("CodigoInitiative").collection("Registered");
            //create document to be inserted
            const pizzaDocument = {
                name: "Pizza",
                shape: "round",
                toppings: [ "Pepperoni", "mozzarella di bufala cheese" ],
            };

            // perform actions on the collection object
            const result = collection.insertOne(pizzaDocument);
            console.log(result.insertedCount);

            // //close the database connection
            client.close();
            res.json({msg: 'all good'})
        });
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM