neurotroph neurotroph - 1 month ago 17
Node.js Question

Replacing text with data from pg-promise

I would like to replace some text in a string with values from a database using

pg-promise
. As I have not used Promises before, I'm struggling with how to deal with it in the best way.

What I have tried so far doesn't work as I try to combine synchronous and asynchronous programming:

var uid = ...;
"Some string".replace(/\#\{([\w]*?)\}/gmi, function(m, c) {
var r = "";
db.one("SELECT a FROM ... WHERE x = $1 AND y = $2", [c, uid])
.then(function(data) {
r = data.a;
});
return r;
});


r
is, unsurprisingly, an empty string. Is there a way to rewrite this block to "wait" for the values from the database?




What I try to do is, to replace placeholders in a message that is send to the user. So the above is part of a function called
prepareMessage
and I send the message to the user using socket.io so it looks something like this:

io.to(socket.id).emit('message', { text: prepareMessage(msg) });

Answer

After some reading and more thinking, I came up with a solution which I'd like to add if someone else has a similar problem.

(In addition to the question above, I had the additional complication that my message is an array of strings and that the order was to be kept.)

The key was to use tasks to send all queries to the DB as one package and wait for all results to return. This led to the following code:

// Sample data
var messages = ["String 1 with no placeholder.",
"String 2, #{placeholder1}, String 2.2.",
"String 3 with some more #{placeholder2}."];

// Collect all matches in array
var matches = [];
messages.forEach(function(text, index) {
  const regex = /\#\{([\w]*?)\}/gmi;
  var m;
  do {
    matches.push(regex.exec(text))
  } while(m);
});

// Request data from the database
db.task(function(t) {
  return t.batch(matches.map(function(m) {
    return t.oneOrNone("SELECT ... FROM ... WHERE id = $1", [m[1]])
  }));
})
.then(function(r) {
        // Replace all occurrences of placeholders
        r.forEach(function(p) {
          messages = messages.map(function(t) { return t.replace("#{"+p.id+"}", p.replacement); });
        });

        // Send message to user
        io.emit('text', messages)M
      })
.catch(function(e) {
        // ... error handling ...
      });