Экспресс не получит возврата другой функции, запрашивающей Mongodb - PullRequest
0 голосов
/ 21 июня 2019

Я работаю с простой аутентификацией API-ключа, я просто хочу проверить данный ключ по предоставленному пользователем ключу.

У меня есть отдельный файл с функцией, запрашивающей базу данных и возвращающей true / false и пользовательский объект.

Но в моем файле route.js возвращаемый объект undefined, даже жестко в моем файле auth.js это не так.

Я попытался сделать функцию в router.get асинхронной функцией, используя express-promise-router, и сделать функцию ожидающей возврата var user = await auth.verify(req.params.uid, req.get("token")), но я действительно не знаю, как работает асинхронность.

router.js

[...]
router.get('/list/:uid', function(req, res) {
  var user = auth.verify(req.params.uid, req.get("token"))
  console.log("User: " + user) // <-- Undefined
  if (user.status) {
    res.send("Success")
  } else {
    res.status(403)
    res.json({status: 403, error: "Unkown User / Token"})
  }
})
[...]

auth.js

var db = require('./db')

var ObjectId = require('mongodb').ObjectId; 

module.exports = {
    verify: (uid, key) => {
        try {
            var collection = db.get().collection('users')
            const obj_id = new ObjectId(uid)
            const query = { _id: obj_id }
            collection.find(query).limit(1).toArray(function(err, user) {
                var status = 0;
                var usr = {};
                if (err) {throw err}else{status=1}
                if (user.length <= 0) {throw "NotExistingExc"; status = 0}else{
                    usr = user[0];
                    if (key != usr.api) status = 0
                }

                var returnObj = {
                    status: status,
                    user: usr
                } /* --> Is {
                              status: 1,
                              user: {
                                       _id: d47a2b30b3d2770606942bf0,
                                       name: 'Sh4dow',
                                       groups: [ 0 ],
                                       api: 'YWFiMDI1MGE4NjAyZTg0MWE3N2U0M2I1NzEzZGE1YjE='
                                    }
                            }
*/

                return returnObj;
            })
        } catch (e) {
            console.error(e)
            return {
                status: 0,
                user: {},
                error: e
            }
        }
    }
}

db.js (Idk, если необходимо)

var MongoClient = require('mongodb').MongoClient

var state = {
  db: null,
}

exports.connect = function(url, done) {
  if (state.db) return done()

  MongoClient.connect(url, { useNewUrlParser: true }, function(err, db) {
    if (err) return done(err)
    state.db = db
    done()
  })
}

exports.get = function() {
  return state.db.db("database")
}

exports.close = function(done) {
  if (state.db) {
    state.db.close(function(err, result) {
      state.db = null
      state.mode = null
      done(err)
    })
  }
}

Я хочу, чтобы returnObj в auth.js в router.get моего файла route.js.

Ответы [ 2 ]

1 голос
/ 21 июня 2019

Сделать auth.verify вернуть Promise, что мы можем затем await для него внутри router. Вы можете просто сделать асинхронный обратный вызов не нужно express-promise-router

router.get('/list/:uid', async function(req, res) {
  try {
    var user = await auth.verify(req.params.uid, req.get("token"))
    console.log("User: " + user)
    if (user.status) {
      res.send("Success")
    } else {
      res.status(403).json({status: 403, error: "Unkown User / Token"})
    }
  } catch (e) {
    console.error(e)
    res.status(/* */).json(/* */)
  }
})

1011 * Auth *

module.exports = {
  verify: (uid, key) => new Promise((resolve, reject) => {
      var collection = db.get().collection('users')
      const obj_id = new ObjectId(uid)
      const query = { _id: obj_id }

      collection.find(query).limit(1).toArray(function(err, user) {
          var status = 0;
          var usr = {};
          if (err) {
            reject(err)
            return
          } else {
            status = 1
          }
          if (user.length <= 0) {
            reject(new Error("NotExistingExc"))
            return
          } else {
            usr = user[0]
            if (key != usr.api) status = 0
          }

          var returnObj = {
              status: status,
              user: usr
          } 

          resolve(returnObj);
      })
  }
}
0 голосов
/ 21 июня 2019

Короче говоря, причина, по которой вы получаете undefined, заключается в том, что код в auth.js является асинхронным .Но ты действительно близко.Метод toArray в MongoDB возвращает обещание , поэтому вам необходимо убедиться, что вы вернули это обещание, а затем правильно использовать его в маршрутизаторе.

В аутентификации.js, убедитесь, что verify возвращает обещание - просто добавьте return !

return collection.find(query).limit(1).toArray(...)

А затем измените использование verify наАсинхронное / ожидание, которое вы изначально пытались:

router.get('/list/:uid', async function(req, res) {
  var user = await auth.verify(req.params.uid, req.get("token"))
  // More code here...
})
...