Search code examples
javascriptmysqlnode.jsalgolia

I have a problem when I try to push the data to Algolia


I am trying to push the data of my data base in Mysql to Algolia. This is the code.

const algoliasearch = require("algoliasearch");
const client = algoliasearch(ALGOLIA_APPLICATION_ID, ALGOLIA_ADMIN_API_KEY);
const index = client.initIndex("demo_ecommerce");
const _ = require('lodash');

var mysql = require('mysql');

var connection = mysql.createConnection({
    host : 'localhost',
    user : 'root',
    password : 'password',
    database : 'ecommerce'
})

connection.connect();

connection.query("SELECT * FROM productos", (err, res) => {
  if (err) throw err;
  const chunks = _.chunk(res, 1000)
  chunks.forEach(chunk => index.saveObjects(chunk))
});

connection.end();

But when i run the code I recieved this error.

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

Could help me with this? What I have to do to resolve it?


Solution

  • First: your connection.connect() does not complete right away. Instead it uses a callback to announce its completion. But you don't have one.

    That's OK, though, because connection.query() connects implicitly. So get rid of both connection.connect() and connection.end() . You don't need 'em.

    Second, you have the line if (err) throw err; That line would be useful if your code was wrapped in a try / catch handler. But it isn't. So, when you throw an error things break. Instead do something like this:

    if (err) {
      console.error(err)
      return
    }
    

    and you'll see the error when MySQL kicks one back to you.

    Third, you are misusing the .saveObjects() method from the algolia package. That method returns a Promise, but you don't wait for it with .then() or await.

    You want to iterate over an array, calling .saveObjects() for each chunk. Here's the most straightforward way to do that, using an async function with an ordinary for loop in it.

    connection.query("SELECT * FROM productos", (err, res) => {
      if (err) {
        console.error(err)
        return
      }
      saveAllObjects (res)
      .then (i => console.log (i, 'chunks saved.))
      .catch (err => console.error (err))
    });
    
    async function saveAllObjects (res) {
      const chunks = _.chunk(res, 1000)
      for (let i = 0; i < chunks.length; i++) {
        await index.saveObjects(chunks[i])
      }
      return chunks.length
    }
    

    This formulation lets your async function await the completion of each .saveObjects() operation before it starts the next.

    Be patient: it takes time to wrap your brain around Javascript's asynchronous nature.