2

I'm learning how to use Sqlite3 with Node, and I'm running into a strange issue. In componentWillMount() on my react front end's main App.js, I make an axios request to the route /all so I can populate a contact list.

What's weird is that, when I hit my other route, /add with a different axios request when I add a contact, it reaches my then() as such,

axios
  .post('/add', contactData)
  .then(res =>
    console.log(`Contact ${contactData.name} added successfully`)
  )
  .catch(err => console.log('Error encountered: ', err));

With a slight delay too, because I setState before making my axios request, which makes me think that the contact is added into the contacts table.

But when I access localhost:5000/all directly, I receive an empty array [] as the response. I'm not sure what's going on.

Here's my server.js

const express = require('express');
const sqlite3 = require('sqlite3');
const path = require('path');
const cors = require('cors');

const dbName = 'my.db';
const tableName = 'Contacts';
const dbPath = path.resolve(__dirname, dbName);

const app = express();

const port = process.env.PORT || 5000;

app.use(cors());

app.listen(port, () => console.log(`Server running on port ${port}`));

app.get('/all', (req, res) => {
  let db = new sqlite3.Database(dbPath);

  let sql = `SELECT number FROM ${tableName}`;

  db.run(
    `CREATE TABLE IF NOT EXISTS ${tableName}(name text, number text, address text)`
  );

  db.all(sql, [], (err, rows) => {
    if (err) {
      return res.status(500).json(err);
    } else {
      return res.json(rows);
    }
  });
});

app.post('/add', (req, res) => {
  let db = new sqlite3.Database(dbPath);

  db.run(
    `INSERT INTO ${tableName}(name, number, address) VALUES(${req.name},${
      req.number
    },${req.address})`,
    [],
    err => {
      if (err) return res.status(500).json(err);
    }
  );

  return res.json({ msg: 'success' });
});

Edit:

I should note that when I navigate to /all I get this,

all

and when I try to post to /add, I get the error

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

No where am I sending multiple responses though.

4

3 回答 3

1

You can fix this issue Using Async-Await in Node.js. JavaScript is asynchronous in nature and so is Node. Asynchronous programming is a design pattern which ensures the non-blocking code execution.

The non-blocking code does not prevent the execution of a piece of code. In general, if we execute in Synchronous manner i.e one after another we unnecessarily stop the execution of those codes which is not depended on the one you are executing.

Asynchronous does exactly opposite, the asynchronous code executes without having any dependency and no order. This improves system efficiency and throughput.

But in some case, we need to wait for the response.

 app.get('/all',async (req, res) => {
  let db = new sqlite3.Database(dbPath);
  let sql = `SELECT number FROM ${tableName}`;
 await db.run(
    `CREATE TABLE IF NOT EXISTS ${tableName}(name text, number text, address text)`
  );
 await  db.all(sql, [], (err, rows) => {
    if (err) {
      return res.status(500).json(err);
    } else {
      return res.json(rows);
    }
  });
});
app.post('/add',async  (req, res) => {
  let db = new sqlite3.Database(dbPath);
  await db.run(
    `INSERT INTO ${tableName}(name, number, address) VALUES(${req.name},${
      req.number
    },${req.address})`,
    [],
    err => {
      if (err) return res.status(500).json(err);
    }
  );
  return res.json({ msg: 'success' });
})
于 2019-02-13T13:08:07.247 回答
1

I would not init your db and create your table every time you hit /all.

Try this:

// get this out of the `/all` route, no need to initialize the db object over and over again
let db = new sqlite3.Database(dbPath);

// also leave this outside the `/all` route:
// no need to create the table over and over again.
db.run(
  `CREATE TABLE IF NOT EXISTS ${tableName}(name text, number text, address text)`
);


app.get('/all', (req, res) => {
  let sql = `SELECT number FROM ${tableName}`;

  // according to the sqlite3 api, the second parameter is optional, so just leave it out:
  db.all(sql, (err, rows) => {
    if (err) return res.status(500).json(err); // if you use return,  you don't need 'else' because the code will never reach it.

    res.json(rows)
  });
});

Your /add route also looks a bit off. Try this:

app.post('/add', (req, res) => {
  // let db = new sqlite3.Database(dbPath);  // remove this as you already defined it at the beginning of your code.

  db.run(
    `INSERT INTO ${tableName}(name, number, address) VALUES(${req.name},${req.number},${req.address})`,
    err => {
      if (err) return res.status(500).json(err);
      res.json({ msg: 'success' }); // put the success in the callback (after the query is run!), else, when you get an error, express.js will try to send an error message AND a success message giving you the error "Can't send headers after they are sent"
    }
  );

});
于 2019-02-13T14:16:01.467 回答
0
await  db.all(sql, [], async (err, rows) => {
    if (err) {
       await return res.status(500).json(err);
    } else {
     await return res.json(rows);
    }
  });
于 2019-02-13T13:24:02.313 回答