Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Synchronous programming using pg-promise

I am new to node.js and pg-promise coming from a synchronis programming background it requires a new thinking.

I would to start with a scenario of running database initialisation before the main program logic.

Following this example: https://github.com/vitaly-t/pg-promise/wiki/Learn-by-Example#simple-select

db.any("select * from users where active=$1", [true])
  .then(function (data) {
    // success;
  })
  .catch(function (error) {
    // error;
  });

Would my code read as either:

db.query("DELETE FROM records")
  .then(function (data) {
    // success;
    console.log("This is where all my main logic goes");
  })
  .catch(function (error) {
    // error;
  });

Or would it read as:

db.query("DELETE FROM records")
  .then(function (data) {
    // success;
  })
  .catch(function (error) {
    // error;
  });
console.log("This is where all my main logic goes");

My understanding is that with the latter the message would be displayed before the records were deleted.

Update: After reading numerous articles on promises and callbacks I understand that pg-promise uses chaining being .then and .catch for both success and error scenarios. I also now believe I understand the pg-promise command should be placed within a function wrapper such as:

function initialiseDB() {
  db.query("DELETE FROM records")
    .then(function (data) {
      // success;
    })
    .catch(function (error) {
      // error;
    });
  }

Then from within my code I would call the function with a simple command which would run the function asynchronously:

initialiseDB();

I am however still unsure of how this concept of asychronous coding and promises fits into the overall structure of a program as surely almost everything in a program would need the initialisation to be completed first. Accordingly would the entire program not need to be placed in the ".then" section of the function? i.e the only code at the top level would effectively be the intialiseDB() function?

// Start of code here 
var pgp = require('pg-promise')();

//Configure the database connection
var config = {
  user:               'username', //env var: PGUSER 
  database:           'database', //env var: PGDATABASE 
  password:           'password', //env var: PGPASSWORD 
};

var db = pgp(config);

function initialiseDB() {
  db.query("DELETE FROM records")
    .then(function (data) {
      // This is where the main program logic goes after this line;
    })
    .catch(function (error) {
      // error;
    });
}

// Commence the program here
initialiseDB();
like image 868
Dercni Avatar asked Aug 01 '16 06:08

Dercni


People also ask

What does PG promise do?

pg-promise is a Postgres library for Node written on top of the brianc/node-postgres library. It's technically a wrapper for node-postgres and converts the callback interface into a promises based interface.

Can promise be synchronous?

A promise is used to handle the asynchronous result of an operation. JavaScript is designed to not wait for an asynchronous block of code to completely execute before other synchronous parts of the code can run. With Promises, we can defer the execution of a code block until an async request is completed.

Does async function return promise?

Async functions always return a promise. If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise. Note: Even though the return value of an async function behaves as if it's wrapped in a Promise.resolve , they are not equivalent.


1 Answers

PG promise actually allows for the use of generators and async/await on newer nodejs versions. Generators require an adapter with promises that vitaly built into the system, so supplying a generator function will allow for a cleaner code flow in a synchronous manner

Taken from the repository under the tag task

Without generators:

db.task(t => {
        // this.ctx = task config + state context;
        return t.one('SELECT * FROM users WHERE id = $1', 123)
            .then(user => {
                return t.any('SELECT * FROM events WHERE login = $1',user.name);
            });
    })
    .then(events => {
        // success;
    })
    .catch(error => {
        // error;
    });

With generators:

db.task(function * (t) {
        // this.ctx = task config + state context;
        let user = yield t.one('SELECT * FROM users WHERE id = $1', 123);
        return yield t.any('SELECT * FROM events WHERE login = $1', user.name);
    })
    .then(events => {
        // success;
    })
    .catch(error => {
        // error
    });

If using async/await, you can simple replace the function * (t) with async function (t) and yield with await and it'll work much the same.

Some caveats:

In more complex logic, you should use try catch blocks around things that might fail, as they'll bubble the error in generators and async/await

db.task(function * (t) {
    yield Promise.reject(new Error('This will cause your app to error')
}

You should also pay close attention to his pg-promise demo! It'll teach you great things like the extend event, repos, external SQL files, and a lot of other great things in the library like helpers!

like image 109
Robert Mennell Avatar answered Oct 02 '22 10:10

Robert Mennell