0

I have a problem with a script in nodejs, using the Q library for promises. The script is supposed to:

  • load a text from a text file,
  • split sentences / words,
  • count all the raw word occurrences,
  • lemmatize the words using an external database (providing the correspondance word->lemma),
  • count all the lemma occurrences.

Everything works fine, except at the end of the script, when I want to display the object containing the informations about lemma counts. The line is this :

Q.allSettled(promises).then(display(lemmaHisto));

It appears that it does not wait for all the promises to be fulfilled before calling the display function, and I couldn't understand why after many attempts and browsing.

Thanks for any help you can give.

Here is my script:

var fs = require('fs');
var _  = require('lodash');
var sqlite3 = require('sqlite3').verbose();
var events = require('events');

var db;
var dbPath = 'incrime.db';
db = new sqlite3.Database(dbPath, sqlite3.OPEN_READONLY);
db.serialize();

var Q = require('q');
var dbget = function (sql) {
  var d = Q.defer();
  db.get(sql, function (err, row) {
    if (err) { d.reject(err); }
    else { d.resolve(row); }
  });
  return d.promise;
};

var rqst = fs.readFileSync('request.sql', {encoding:'utf-8'});
var txt = fs.readFile('txt/sample.txt', {encoding:'utf-8'}, analysis);

function analysis(err, data) {
  var sentences = data.split(/[.!?]+\s/g);
  var wordHisto = {};
  var lemmaHisto = {};

  var indexWord = function (w) {
    if (wordHisto[w]) { wordHisto[w] += 1; } 
    else { wordHisto[w] = 1; }
  };

  var indexLemma = function (word) {
    var obj = lemmaHisto;
    var qty = wordHisto[word];
    return function (row) {
      var w = row.lemme ? row.lemme : word;
      if (obj[w]) { obj[w] += qty; } 
      else { obj[w] = qty; }
      return qty;
    };
  };

  _.each(sentences, function(s) {
    s = s.toLowerCase();
    var words = s.match(/[a-zéàèâêîôûäëïü-]{3,}/g);
    _.each(words, indexWord);
  });

  var promises = [];

  _.each(_.keys(wordHisto), function(w) {
    var sql = rqst.replace('%word%', w);
    var promise = dbget(sql).then(indexLemma(w), console.error);
    promises.push(promise);
    return promise;
  });

  Q.allSettled(promises).then(display(lemmaHisto));
}

function display (obj) {
  var d = Q.defer();
  console.log('display:', obj);
  d.resolve();
  return d.promise;
}

The output I get is simply:

display: {}
glmxndr
  • 45,516
  • 29
  • 93
  • 118

1 Answers1

4

display() is being called when the parser reaches that line, that's why there's no items in your object or "it's not waiting", as you state.

What you should do is the following:

Q.allSettled(promises).then(function() {
  display(lemmaHisto);
});
gustavohenke
  • 40,997
  • 14
  • 121
  • 129