new Q Open Wid
new Q Open Wid

Reputation: 2283

Repl.it unhandled promise rejection

I wanted to implement a rudimentary leaderboard to my game on Repl.it, so I created a node.js backend. This is what I have on the backend:

const express = require('express');
const Client = require('@replit/database');
const db = new Client();

const cors = require('cors');
const bcrypt = require('bcrypt');
const bodyParser = require('body-parser');

const server = express();
server.use(cors());
server.use(bodyParser.json());
server.use(bodyParser.urlencoded({ extended: false }));

server.get('/', (req, res) => {
  res.send('Online');
});

server.post('/leaderboard', async (req, res) => {
  const m = await db.get('leaderboard');
  m.push({
    score: parseInt(req.body.score, 10),
    time: new Date()
  });
  m.sort((a, b) => b.score - a.score);
  await db.set('leaderboard', m);
    
  res.send(req.body);
});

server.get('/leaderboard', async (req, res) => {
  const leaderboard = await db.get('leaderboard');
  res.json(leaderboard);
});

server.listen(3000);

But whenever I try to POST, I get the following error:

(node:344) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'push' of null

(node:344) 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:344) [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.

And if I try to GET, res returns null - probably since I'm not pushing anything when doing POST.

Why is this happening, and how do I fix it?

Upvotes: 0

Views: 440

Answers (1)

Mulan
Mulan

Reputation: 135357

How to handle the promise rejection?

You're getting the UnhandledPromiseRejectionWarning because you have nothing to catch the errors happening in your asynchronous routes. See the express error handling guide. You need to attach some kind of error handler -

var bodyParser = require('body-parser')

app.use(bodyParser.urlencoded({
  extended: true
}))
app.use(bodyParser.json())
app.use(...)

// error handler
app.use(function (err, req, res, next) {
  console.error(err.stack)
  res.status(500).send('Something broke!')
})

app.post(...)

app.get(...)

...

Calls to next() and next(err) indicate that the current handler is complete and in what state. next(err) will skip all remaining handlers in the chain except for those that are set up to handle errors...

Why is the promise rejected?

The error is happening because m is null and null does not have a .push method. Calling null.push(...) throws an error which causes the promise to be rejected with this error.

Why does m have a null value?

I don't know the repl.it API, but presumably there is no value for db.get('leaderboard') and that is why m is getting a null response. You could try fixing it like this

server.get('/leaderboard', async (req, res) => {
  const leaderboard = (await db.get('leaderboard')) || [] // <-
  res.json(leaderboard);
});

server.post('/leaderboard', async (req, res) => {
  const m = (await db.get('leaderboard')) || [] // <-
  // ...
});

Adding ... || [] to the result says if the response of db.get is falsey (null is falsey), use the empty array, [], instead.

replit/database

set(key: string, value: any): promise<void>
get(key: string): promise<any | null>
get(key: string, {raw: true}): promise<string | null>

set automatically encodes the value using JSON.stringify.

get is designed to retrieve JSON strings and automatically decode them. If no string is found, a null value returned, which is what your were experiencing.

Note, you can use db.get(someKey, {raw: true}) to get the raw string back, skipping the JSON.parse step.

Upvotes: 1

Related Questions