简体   繁体   中英

Node.js & MongoDB: why the db object is undefined?

I'm using Node.js, Hapi and MongoDB Native Driver ( node-mongodb-native )

I want to access the db object returned by the get() method from db.js in my handler in server.js .

db.js

'use strict'

const MongoClient = require('mongodb').MongoClient

let _db

function connect (url) {
  return MongoClient.connect(url, { server: { poolSize: 5 } })
  .then((db) => {
    _db = db
    console.log('Connected to MongoDB:', db.s.databaseName)
  })
  .catch((e) => {
    throw e
  })
}

function get () {
  return _db
}

function close () {
  if (_db) {
    console.log('Closing MongoDB connection.')
    _db.close()
  }
}

module.exports = {
  connect,
  close,
  get
}

server.js

'use strict'

const Hapi = require('hapi')

const Db = require('./db')
const _db = Db.get()

const server = new Hapi.Server()

server.connection({
  host: 'localhost',
  port: 8080
})

server.route({
  method: 'GET',
  path: '/',
  handler: (req, rep) => {
    console.log(_db) // _db is undefined
  }
})

Db.connect('mongodb://localhost:27017/test')
.then(() => {
  server.start((err) => {
    if (err) {
      throw err
    }
    console.log(`Server running at: ${server.info.uri}`)
  })
})
.catch((e) => {
  console.error(`${e.name}: ${e.message}`)
  return
})

The problem is that Db.get() return undefined .

Now consider this code instead:

const Db = require('./db')

const server = new Hapi.Server()

...

server.route({
  method: 'GET',
  path: '/',
  handler: (req, rep) => {
    const _db = Db.get()
    console.log(_db) // the _db object exists
  }
})

I don't understand why the first code return undefined as the get() method is called and should store the instance into _db thus accessible in the handler function.

The value of _db is assigned in a function passed to then of a Promise, the execution of this part is deferred to a point in time until the Promise has been resolved. The server.route is synchronous. It means it will be very likely executed before the Promise has been resolved.

To make it work, wait until the Promise has been resolved:

'use strict'

const MongoClient = require('mongodb').MongoClient

let _db

async function connect (url) {
  try {
    return await MongoClient.connect(url, { server: { poolSize: 5 } })
  } catch (error) {
    throw new Error('Could not connect to Mongo instance');
  }
}

async function get () {
  return _db ? _db : await connect();
}

async function close () {
  if (_db) {
    console.log('Closing MongoDB connection.')
    _db.close()
  }
}

module.exports = {
  connect,
  close,
  get
}

and then

'use strict'

const Hapi = require('hapi')

const Db = require('./db')
const _db = await Db.get()

const server = new Hapi.Server()

server.connection({
  host: 'localhost',
  port: 8080
})

server.route({
  method: 'GET',
  path: '/',
  handler: async (req, rep) => {
    const _db = await Db.get();
    console.log(_db) // _db will be guaranteed to be a valid object, otherwise an error will be thrown
  }
})

Db.connect('mongodb://localhost:27017/test')
.then(() => {
  server.start((err) => {
    if (err) {
      throw err
    }
    console.log(`Server running at: ${server.info.uri}`)
  })
})
.catch((e) => {
  console.error(`${e.name}: ${e.message}`)
  return
})

Read more about async/await there and there .

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