ApprenticeDev ApprenticeDev - 2 months ago 13
Node.js Question

Counting instances of error case in node / JavaScript MySQL callback

Can anyone tell me why

countDups
always elucidates to
0
and the assignment
countDups += 1;
in the callback
mySQLCallback
isn't respected?

Where should i Use
console.log(countDups)
to get the number of times the error
'ER_DUP_ENTRY'
was thrown?

I have tried all positions in the code, and declaring the variable
countDups
inside / outside every function.

I realise I can
console.log(countDups)
inside the
.each
loop, and print out every increment - but I'm only interested in the final value of
countDups
, not the value at every iteration. [Thanks to Svabael]

EDIT - Interestingly, I can make this work with promises or the async library but not with standard callbacks as per below. So thanks for any suggestions about other methods, but I'm interested in standard callbacks here specifically.

'use strict';

const url = require('url'),
fs = require('fs'),
cheerio = require('cheerio'),
moment = require('moment'),
mysql = require('mysql'),
request = require('request');

var connection = mysql.createConnection({
host : 'host',
user : 'user',
password : 'pass',
database : 'db'
});


var opt = {
url: "http://www.google.co.uk/",
json: "",
credentials: "",
method: 'GET'
};


var countDups = 0;


var mySQLCallback = function(err, rows, fields) {

if (err && err.code == 'ER_DUP_ENTRY'){

countDups += 1;

return;

}
};

request(opt, function(err, response, body) {

if(err) {
console.log(err);
}

var $ = cheerio.load(body);

var tds = $('element');

tds.each(function(){

if (err) throw err;

var type = $(this);

var typeObj = {TYPE:type};

connection.query('INSERT INTO TABLE SET ?', urlObj , mySQLCallback);

});



connection.end();

console.log(countDups);



});

Answer

In the place that you have right now the console.log it will not work because you are increasing the counter in the callback of the query execution that is an async operation. If you place the console.log inside the error block then you should be able to see the counter increasing when you will find an error.

EDIT Definitely there are more elegant ways to do it. In this case I've used a variable that plays the role of a semaphore. On every tds.each iteration we are increasing the var and every time that we have a response from the query we are decreasing it. When it will be zero, it means that we can safely return the results.

'use strict';

const url = require('url'),
  fs = require('fs'),
  cheerio = require('cheerio'),
  moment = require('moment'),
  mysql = require('mysql'),
  request = require('request');

var connection = mysql.createConnection({
  host: 'host',
  user: 'user',
  password: 'pass',
  database: 'db'
});

var opt = {
  url: "http://www.google.co.uk/",
  json: "",
  credentials: "",
  method: 'GET'
};

var countDups = 0;

function getLastCount (countDups) {
  console.log(countDups);
}

request(opt, function (err, response, body) {
  if (err) {
    console.log(err);
  }

  var $ = cheerio.load(body);

  var tds = $('element');
  var i = 0;

  tds.each(function () {
    if (err) { 
      throw err;
    }

    i++;

    var type = $(this);

    var typeObj = { TYPE: type };

    connection.query('INSERT INTO TABLE SET ?', urlObj, function (err, rows, fields) {
      if (err && err.code == 'ER_DUP_ENTRY') {
        countDups += 1;
        console.log(countDups);
      }

      i--;

      if (i === 0) {
        getLastCount(countDups);
      }

    });
  });

  connection.end();
});