Search code examples
node.jspg-promise

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) });


Solution

  • 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 ...
          });