узел mysql: невозможно установить заголовки после их отправки

0

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

Я использую NodeJS/Express и mysql.

Вот мой код до сих пор:

exports.checkForMovies = function (req, res, next) {
  const testFolder = './test/';
  var movieList = [];
  var movieResultsPromise = [];
  var movieResults = [];

  fs.readdirSync(testFolder).forEach(file => {
    movieList.push(tnp(file));
  });

  movieList.forEach(movie => {
    var waitPromise = searchTMDB(movie.title);
    movieResultsPromise.push(waitPromise);
  });

  Promise.all(movieResultsPromise).then(result => {
    movieResults = result;

    movieResults.forEach(movie => {
      checkMoviesInDB(movie.id, (err, data) => {
        if (err) {
          console.log(err)
        }

        if (data && data.update === true) {

          var movieObj = {
            m_tmdb_id: movie.id
          };

          insertMoviesToDB(movieObj, (resp, err) => {
            if (err) {
              console.log(err);
            } else {
              return res.json(resp);
            }
          });
        } else {
          return res.json(data);
        }
      });
    });
  });
}

function checkMoviesInDB(id, cb) {
  var sql = "SELECT * FROM ?? WHERE m_tmdb_id = ?"
  var table = ['movie', id];

  sql = mysql.format(sql, table);

  connection.query(sql, function (err, rows) {
    if (err) {
      return cb(err);
    }

    if (rows.length > 0) {
      return cb(null, {
        success: true,
        update: false,
        message: 'Movies up to date!'
      })
    } else {
      return cb(null, {
        update: true,
        message: 'Updating database!'
      })
    }
  });
}

function insertMoviesToDB(movie, cb) {
  var sql = "INSERT INTO ?? SET ?";
  var table = ['movie', movie];

  sql = mysql.format(sql, table);

  connection.query(sql, function (err, rows) {
    if (err) {
      return cb(err);
    } else {
      return cb(null, {
        success: true,
        message: 'Movie database updated!'
      })
    }
  });
}

function searchTMDB(title) {
  return new Promise((resolve, reject) => {
    https.get(config.tmdbURL + title, response => {
      var body = "";
      response.setEncoding("utf8");

      response.on("data", data => {
        body += data;
      });
      response.on("end", () => {
        body = JSON.parse(body);
        resolve(body.results[0]);
      });
      response.on("error", (err) => {
        reject(err);
      });
    });
  });
}

После выполнения кода он вставляет информацию о фильме в базу данных или отвечает "Фильмы в актуальном состоянии", но я получаю эту ошибку, и происходит сбой NodeJS:

Ошибка: невозможно установить заголовки после их отправки.

Любая помощь приветствуется, спасибо!

РЕДАКТИРОВАТЬ!

Это новый код, и я все еще получаю ту же ошибку...

exports.checkForMovies = function (req, res) {
  const testFolder = './test/';
  var movieList = [];
  var movieResults = [];

  fs.readdirSync(testFolder).forEach(file => {
    movieList.push(tnp(file));
  });


  var movieObj = movieList.map(movie => {
    var tmp = [];
    return searchTMDB(movie.title).then(data => {
      tmp.push(data);
      return tmp
    });
  });

  var checkDB = Promise.all(movieObj).then(moviesData => {
    moviesData.map(movieData => {
      checkMoviesInDB(movieData[0]).then(checkResponse => {
        if (!checkResponse.movieToInsert) {
          res.json(checkResponse);
        } else {
          var insertArray = checkResponse.movieToInsert;
          var inserting = insertArray.map(movie => {

            var movieObject = {
              m_tmdb_id: movie.id,
              m_name: movie.title,
              m_year: movie.release_date,
              m_desc: movie.overview,
              m_genre: undefined,
              m_poster: movie.poster_path,
              m_watched: 0
            };

            insertMoviesToDB(movieObject).then(insertResponse => {
              res.json(insertResponse);
            });
          });
        }
      });
    });
  });
}

function checkMoviesInDB(movie) {
  var moviesToInsert = [];

  return new Promise((resolve, reject) => {
    var sql = "SELECT * FROM ?? WHERE m_tmdb_id = ?"
    var table = ['movie', movie.id];

    sql = mysql.format(sql, table);

    connection.query(sql, function (err, rows) {
      if (err) {
        return reject(err);
      }

      if (rows.length === 0) {
        moviesToInsert.push(movie);
        resolve({
          success: true,
          movieToInsert: moviesToInsert
        });
      } else {
        resolve({
          success: true,
          message: 'No movie to insert'
        });
      }
    });
  });
}

function insertMoviesToDB(movie) {
  return new Promise((resolve, reject) => {
    var sql = "INSERT INTO ?? SET ?";
    var table = ['movie', movie];

    sql = mysql.format(sql, table);

    connection.query(sql, function (err, rows) {
      if (err) {
        return reject(err);
      } else {
        resolve({
          success: true,
          message: 'Movie added!'
        });
      }
    });
  });
}

function searchTMDB(title) {
  return new Promise((resolve, reject) => {
    https.get(config.tmdbURL + title, response => {
      var body = "";
      response.setEncoding("utf8");

      response.on("data", data => {
        body += data;
      });
      response.on("end", () => {
        body = JSON.parse(body);
        resolve(body.results[0]);
      });
      response.on("error", (err) => {
        reject(err);
      });
    });
  });
}

Auth.js

const config = require('./config');
const jwt = require('jsonwebtoken');

module.exports = function (req, res, next) {

    var token = req.body.token || req.params.token || req.headers['x-access-token'];

    if (token) {
        jwt.verify(token, config.secret, function (err, decoded) {
            if (err) {
                return res.json({
                    success: false,
                    message: 'Failed to authenticate token.'
                });
            } else {
                req.decoded = decoded;
                next();
            }
        });
    } else {
        return res.status(403).send({
            success: false,
            message: 'Please login in to countinue!'
        });
    }

};
  • 0
    Это происходит, вероятно, так как вы не используете next()
  • 0
    Я получаю ту же ошибку, используя next ()
Показать ещё 9 комментариев
Теги:
express

1 ответ

1

Надеюсь это поможет:

// Bad Way
const checkForMovies = (req, res) => {
  const movieList = ['Braveheart', 'Highlander', 'Logan'];
  movieList.forEach(movie => {
    res.json(movie);   // Will get Error on second loop: Can't set headers after they are sent.
  })
}

// Good Way
const checkForMovies = (req, res) => {
  const movieList = ['Braveheart', 'Highlander', 'Logan'];
  const payload = { data: { movieList: [] } };
  movieList.forEach(movie => {
    payload.data.movieList.push(movie);
  });
  // send res once after the loop with aggregated data
  res.json(payload);
}

/* GET home page. */
router.get('/', checkForMovies);

Ещё вопросы

Сообщество Overcoder
Наверх
Меню