0

I want to show the leaderboard rank before and after the user.

file leaderboard.js:

exports.leaderboarduser = userName =>
  new Promise((resolve, reject) => {
    const player = user.findOne({ userName: userName });
    const next_player = user
      .find({ _id: { $ne: player._id }, score: { $gte: player.score } })
      .sort({ score: 1, userName: 1 })
      .limit(-1)[0];
    const previous_player = user
      .find({ _id: { $ne: player._id }, score: { $lte: player.score } })
      .sort({ score: -1, userName: -1 })
      .limit(-1)[0]
      .then(users => {
        resolve(users);
      })
      .catch(err =>
        reject({ status: 500, message: "Internal Server Error !" })
      );
  });

When run:

(node:18753) UnhandledPromiseRejectionWarning: RangeError [ERR_HTTP_INVALID_STATUS_CODE]: Invalid status code: undefined at ServerResponse.writeHead (_http_server.js:209:11) at ServerResponse.writeHead (/root/game/node_modules/on-headers/index.js:44:26) at ServerResponse._implicitHeader (_http_server.js:200:8) at write_ (_http_outgoing.js:585:9) at ServerResponse.end (_http_outgoing.js:702:5) at ServerResponse.send (/root/game/node_modules/express/lib/response.js:221:10) at ServerResponse.json (/root/game/node_modules/express/lib/response.js:267:15) at leaderboard.leaderboarduser.then.catch.err (/root/game/routes.js:152:42) at process._tickCallback (internal/process/next_tick.js:68:7) (node:18753) 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(). (rejection id: 2) (node:18753) [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.

How can I solve this?

ambianBeing
  • 3,449
  • 2
  • 14
  • 25

1 Answers1

0

Not sure if you really need multiple queries, coz i don't have any idea about your database structure. Here is the sorted code:

exports.leaderboarduser = (userName) => {
    return new Promise(async (resolve, reject) => {
        try {
            const current_player = await user.findOne({ userName: userName });

            const next_playerResult = await user.find({ _id: { $ne: player._id }, score: { $gte: player.score } }).sort({ score: 1, userName: 1 }).limit(1);
            const next_player = next_playerResult[0] || {};

            const previous_playerResult = await user.find({ _id: { $ne: player._id }, score: { $lte: player.score } }).sort({ score: -1, userName: -1 }).limit(1);
            const previous_player = previous_playerResult[0] || {};
            resolve([current_player, next_player, previous_player]);        // change the order as per requirement
            // OR better send an object like: resolve({ current_player, next_player, previous_player });
        } catch (err) {
            reject(err);
        }
    });
}

The problem is you are not calling async functions properly. Also there is no catch block to handle the errors. I've used async/await inside the promise to handle async db calls. And then somewhere in your project you can call this function as:

leaderboarduser('testName')
    .then((users) => {
        console.log("users are: ", users);
    ...
    // do something with users
})
    .catch((err) => {
        console.log("Error: ", err);
    ...
    // handle error
});

Also limit() in mongoose is used to limit the number of records. Since in your case you need only one record, you should pass 1 and not -1.

Hope this helps :)

Mohammed Amir Ansari
  • 2,311
  • 2
  • 12
  • 26
  • 2
    [Never pass an `async function` as the executor to `new Promise`](https://stackoverflow.com/q/43036229/1048572)! – Bergi Sep 27 '19 at 23:13